编译android使用的so库必须通过android的ndk提供的c和c++来进行编译,ndk的下载地址https://developer.android.com/ndk/downloads
go的源代码有几点注意:
import "C"
//export
导出标识,注意//
与export
之间不能有空格func main() {}
main方法需要留空进入到ndk的根目录cd /path/to/ndk
,执行命令生成对应环境的工具链./build/tools/make-standalone-toolchain.sh --toolchain=x86_64-4.9 --platform=android-29 --install-dir=~/Library/toolchain-x86_64
注意:
--toolchain
参数指定了该工具链的平台,可用平台可以在ndk根目录下的toolchains
目录中查看--install-dir
参数指定了生成的工具链存放位置平台架构标识说明:
x86
x86架构的32位版本x86_64
x86架构的64位版本arm
arm架构的32位版本aarch64
arm架构的64位版本编译时需要指定GOOS
、GOARCH
、CGO_ENABLED
、CC
等环境变量,这里尤其要注意,当GOOS
为android
时,CGO_ENABLED
会被设置为0,而CGO_ENABLED
设置为0将会无法编译,提示错误go: no Go source files
编译命令env GOOS=android GOARCH=amd64 CGO_ENABLED=1 NDK_TOOLCHAIN=$TOOLCHAINX8664 CC=$TOOLCHAINX8664/bin/x86_64-linux-android-gcc go build -buildmode=c-shared -o=libc-shared.so ./src/main/c-shared.go
编译后如果没有问题会在当前目录下生成libc-shared.h
与libc-shared.so
两个文件,其中的so
文件可被android加载
注意事项:
$TOOLCHAINX8664
指向上一个步骤中编译出的工具链的根目录CC
使用的架构类型应该跟你要编译的目标平台一致android可以通过jna(jni的易用版)来加载so库,在安卓项目的app/build.gradle
中的android
配置下新增以下jni配置
sourceSets {
main {
jniLibs.srcDirs = ['libs']
}
}
之后在app
目录下新建一个文件夹libs
,以及其子文件夹x86_64
(对应到不同的架构),将编译好的so
库文件放到对应架构的目录下
添加项目的jna依赖,将一下代码行加入到android项目app
目录下的build.gradle
文件中的dependencies
部分
implementation 'net.java.dev.jna:jna:5.5.0'
之后在这里https://github.com/java-native-access/jna/tree/master/dist下载对应平台的jar文件,android项目需要下载android-xxx.jar
,具体取决于你支持的平台类型
下载后解压jar xf android-xxx.jar
得到libjnidispatch.so
,将该so库拷贝到android项目下的app/libs/x86_64
目录下,并且将前边生成的libc-shared.so
也拷贝进去
在项目中定义一个接口用于加载原生方法,示例代码:
import com.sun.jna.Library;
import com.sun.jna.Native;
private interface GoToNet extends Library {
GoToNet INSTANCE = Native.load("c-shared", GoToNet.class);
String hello();
}
其中hello
方法即是用go编写的函数,该方法可以通过GoToNet.INSTANCE.hello()
的形式来调用
注意:
libjnidispatch.so
以及libc-shared.so
,分别下载或编译并拷贝过去就行了