为 Kotlin android 编译库,rust and go
Compile libraries for Kotlin android,rust and go
这个问题本质上是探索性的,不确定这是否适合堆栈溢出问答。
上下文:
我有一个用 golang 编写的库,我需要编译它以供多个服务使用。
这些服务在 Kotlin android、Rust、Golang 中。
我知道的唯一选择是使用类似 SWIG 的东西来编译不同语言的 go 库。
问题:
- 我认为 SWIG 不适用于 Kotlin。
我正在努力寻找最好的方法来做到这一点以及可以做到这一点的不同方法。
对于任何可以生成 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");
}
%}
// Assuming you don't care about these in your library silence/neaten stuff
#define _Complex
%ignore _GoString_;
%ignore GoComplex64;
%ignore GoComplex128;
%ignore GoSlice;
%ignore GoInterface;
%include "golib.h"
这是一个相当标准的 SWIG 接口,用于定位 Java - 它在生成的头文件中隐藏了一些我们不关心的内容,并使用 Java 自动加载 .so 文件给我们的 pragma。
然后我整理了一个小的 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
我很想使用 -buildmode=c-archive
去构建一个静态库,然后 link 将其放入 SWIG 共享对象中,而不是只是为了让事情在这方面更简单。
这个问题本质上是探索性的,不确定这是否适合堆栈溢出问答。
上下文:
我有一个用 golang 编写的库,我需要编译它以供多个服务使用。
这些服务在 Kotlin android、Rust、Golang 中。
我知道的唯一选择是使用类似 SWIG 的东西来编译不同语言的 go 库。
问题:
- 我认为 SWIG 不适用于 Kotlin。
我正在努力寻找最好的方法来做到这一点以及可以做到这一点的不同方法。
对于任何可以生成 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");
}
%}
// Assuming you don't care about these in your library silence/neaten stuff
#define _Complex
%ignore _GoString_;
%ignore GoComplex64;
%ignore GoComplex128;
%ignore GoSlice;
%ignore GoInterface;
%include "golib.h"
这是一个相当标准的 SWIG 接口,用于定位 Java - 它在生成的头文件中隐藏了一些我们不关心的内容,并使用 Java 自动加载 .so 文件给我们的 pragma。
然后我整理了一个小的 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
我很想使用 -buildmode=c-archive
去构建一个静态库,然后 link 将其放入 SWIG 共享对象中,而不是只是为了让事情在这方面更简单。