为Kotlin Android、Rust和Go编译库。

huangapple go评论87阅读模式
英文:

Compile libraries for Kotlin android,rust and go

问题

这个问题是探索性质的,不确定是否适合在Stack Overflow上提问和回答。

背景:

我有一个用Go语言编写的库,我需要编译成多个服务可以使用的形式。

这些服务分别是Kotlin Android、Rust和Go。

我所知道的唯一选项是使用类似SWIG的工具将Go库编译成不同的语言。

问题:

  1. 我不认为SWIG适用于Kotlin。

我正在寻找最佳方法来解决这个问题,以及可以采用的不同方法。

英文:

This question is exploratory in nature, not sure if this fits stack overlflow Q&A.

Context:

I have a library written in golang that I need to compile for multiple services to use.

These services are in Kotlin android,Rust,Golang.

The only option I am aware of is using something like SWIG to compile the go library for different languages.

Problem:

  1. I don't think SWIG works for Kotlin.

I am trying to fish for the best methods to do this and different approaches this can be done.

答案1

得分: 2

对于任何能生成C共享库和头文件的语言,您可以使用SWIG进行封装。同样,对于任何在JVM中运行并能调用Java类的语言,您可以使用SWIG的自动生成的Java绑定。

因此,我们可以按照以下顺序进行一系列操作:

Go -> C -> JNI -> Java -> Kotlin

实际上相当简单。我下面提供了一个示例来展示它的工作原理,因为我之前从未编写过Go或Kotlin。(因此,请对此持保留意见,我可能没有遵循最佳实践!)

此示例假设您已经安装了JDK/JRE、C编译器、Go和kotlinc。

我的demo.go文件如下所示:

package main

import (
    "C"
    "fmt"
)

//export TestGoFunc
func TestGoFunc(str *C.char) *C.char {
        fmt.Printf("Got string: %s\n", C.GoString(str))
        return nil
}

func main() {}

而hello.kt文件如下所示:

fun main() {
    println("Hello, World!")
    test.TestGoFunc("Another string")
}

为了封装它,我编写了以下SWIG接口:

%module test

%{
#include "golib.h"
%}

%include <typemaps.i>

%pragma(java) jniclasscode=%{
  static {
    System.loadLibrary("test");
  }
%}

// 假设您不关心库中的这些内容,静音/整理一些东西
#define _Complex
%ignore _GoString_;
%ignore GoComplex64;
%ignore GoComplex128;
%ignore GoSlice;
%ignore GoInterface;

%include "golib.h"

这是一个针对Java的相当标准的SWIG接口,它隐藏了我们不关心的一些生成的头文件中的内容,并使用一个pragma在Java中自动加载.so文件。

然后,我编写了一个小型的Makefile来构建所有内容,因为构建过程中有很多步骤:

all: libtest.so hello.jar

golib.so: demo.go
        go build -o golib.so -buildmode=c-shared demo.go

test_wrap.c: golib.so test.i
        swig3.0 -java -Wall test.i

libtest.so: test_wrap.c
        gcc -shared -Wall -Wextra test_wrap.c -o libtest.so ./golib.so -I/usr/lib/jvm/default-java/include/ -I/usr/lib/jvm/default-java/include/linux

hello.jar: hello.kt
        javac *.java
        kotlinc hello.kt -include-runtime -d hello.jar -cp .
        jar uvf hello.jar *.class

如果我们构建并运行这个项目,一切都会很好:

$ make
go build -o golib.so -buildmode=c-shared demo.go
swig3.0 -java -Wall test.i
gcc -shared -Wall -Wextra test_wrap.c -o libtest.so ./golib.so -I/usr/lib/jvm/default-java/include/ -I/usr/lib/jvm/default-java/include/linux
javac *.java
kotlinc hello.kt -include-runtime -d hello.jar -cp .
jar uvf hello.jar *.class
adding: test.class(in = 302) (out= 216)(deflated 28%)
adding: testJNI.class(in = 389) (out= 268)(deflated 31%)
$ LD_LIBRARY_PATH=. java -jar hello.jar
Hello, World!
Got string: Another string

我建议在Go中使用-buildmode=c-archive来构建静态库,然后将其链接到SWIG共享对象中,以保持事情更简单。

英文:

For any language that can generate a C shared library and header file you can use SWIG to wrap it. Equally for any language that runs within a JVM and can call Java classes you can make use of SWIG's auto generated Java bindings.

With that we can therefore do a sequence of things that looks like this:

Go -> C -> JNI -> Java -> Kotlin

It's actually fairly sane. I've put together an example below for this to show how it works since I was curious having never written Go nor Kotlin before. (Take this with a pinch of salt therefore, I've probably not hit "best practice" for either!)

This example assumes you have a working JDK/JRE, C compiler, Go installation and kotlinc.

My demo.go looks like this:

package main

import (
    &quot;C&quot;
    &quot;fmt&quot;
)

//export TestGoFunc
func TestGoFunc(str *C.char) *C.char {
        fmt.Printf(&quot;Got string: %s\n&quot;, C.GoString(str))
        return nil
}

func main() {}

And hello.kt looks like this:

<!-- language: kotlin -->

fun main() {
    println(&quot;Hello, World!&quot;)
    test.TestGoFunc(&quot;Another string&quot;)
}

To wrap this I wrote the following SWIG interface:

<!-- language: c -->

%module test

%{
#include &quot;golib.h&quot;
%}

%include &lt;typemaps.i&gt;

%pragma(java) jniclasscode=%{
  static {
    System.loadLibrary(&quot;test&quot;);
  }
%}

// Assuming you don&#39;t care about these in your library silence/neaten stuff
#define _Complex
%ignore _GoString_;
%ignore GoComplex64;
%ignore GoComplex128;
%ignore GoSlice;
%ignore GoInterface;

%include &quot;golib.h&quot;

This is a fairly standard SWIG interface for targeting Java - it hides some of the stuff in the generated header file we don't care about and autoloads the .so file inside Java using a pragma for us.

Then I put together a small Makefile to build everything since there's a bunch of steps to this build:

<!-- language: none -->

all: libtest.so hello.jar

golib.so: demo.go
        go build -o golib.so -buildmode=c-shared demo.go

test_wrap.c: golib.so test.i
        swig3.0 -java -Wall test.i

libtest.so: test_wrap.c
        gcc -shared -Wall -Wextra test_wrap.c -o libtest.so ./golib.so -I/usr/lib/jvm/default-java/include/ -I/usr/lib/jvm/default-java/include/linux

hello.jar: hello.kt
        javac *.java
        kotlinc hello.kt -include-runtime -d hello.jar -cp .
        jar uvf hello.jar *.class

If we build and run this then it all works nicely:

<!-- language: none -->

$ make
go build -o golib.so -buildmode=c-shared demo.go
swig3.0 -java -Wall test.i
gcc -shared -Wall -Wextra test_wrap.c -o libtest.so ./golib.so -I/usr/lib/jvm/default-java/include/ -I/usr/lib/jvm/default-java/include/linux
javac *.java
kotlinc hello.kt -include-runtime -d hello.jar -cp .
jar uvf hello.jar *.class
adding: test.class(in = 302) (out= 216)(deflated 28%)
adding: testJNI.class(in = 389) (out= 268)(deflated 31%)
$ LD_LIBRARY_PATH=. java -jar hello.jar
Hello, World!
Got string: Another string

I'd be tempted to use -buildmode=c-archive for Go to build a static library and then link that into the SWIG shared object instead just to keep things simpler in that regards though.

huangapple
  • 本文由 发表于 2022年6月1日 23:19:08
  • 转载请务必保留本文链接:https://go.coder-hub.com/72464343.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定