golang
flutter
开发环境和工具
All products License
Go 部分
go 源码
add_library.go
package main
import "C"
//export add
func add(x, y int) int {
return x + y
}
//export remove_int
func remove_int(x, y int) int {
return x - y
}
func main() {
}
这里有几点要注意
//export 方法名//exportremove
编译
我在项目里内置了两个脚本, 一个是编译 android 的, 一个是编译 macOS 的, 因为篇幅和主题的原因, macOS 的就不单独拿出来了
看看编译成安卓的脚本吧
export ANDROID_NDK_HOME=$ANDROID_HOME/ndk/21.0.6113669
export GOARCH=arm
export GOOS=android
export CGO_ENABLED=1
export CC=$ANDROID_NDK_HOME/toolchains/llvm/prebuilt/darwin-x86_64/bin/armv7a-linux-androideabi21-clang
go build -buildmode=c-shared -o output/android/armeabi-v7a/libadd.so add_library.go
echo "Build armeabi-v7a success"
export GOARCH=arm64
export GOOS=android
export CGO_ENABLED=1
export CC=$ANDROID_NDK_HOME/toolchains/llvm/prebuilt/darwin-x86_64/bin/aarch64-linux-android21-clang
go build -buildmode=c-shared -o output/android/arm64-v8a/libadd.so add_library.go
echo "Build arm64-v8a success"
简单来说 有几个环境变量要设置一下
21.0.6113669-buildmode=c-sharedgo help buildmodec-sharedSystem.loadLibrary("xxx")System.loadLibrary("libxxx")
go tool dist list
我这里 1.14.6 包含的 android 对应的是:
$ go tool dist list|grep android
android/386
android/amd64
android/arm
android/arm64
arm 和 arm64 对应 v7 和 v8
386 amd64 应该对应的是 x86 和 x86_64, 这个没有实测, 如果有需要的朋友可以自己尝试一下
./build_android_on_mac.sh
安卓
创建项目
就是简单的在 Android Studio 中 New Project
CMakeLists.txt
CMakeLists.txt
cmake_minimum_required(VERSION 3.10.2)
project(android_lib)
set(GO_BUILD_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../go/output/android)
set(SRC ${GO_BUILD_PATH}/${CMAKE_ANDROID_ARCH_ABI})
include_directories(${SRC})
find_library(
std-lib
android
)
message("CPU ABI: ${CMAKE_ANDROID_ARCH_ABI}")
if (${CMAKE_ANDROID_ARCH_ABI} EQUAL "armeabi") ## 根据ABI的不同, 复制so文件到对应的文件夹
file(COPY ${GO_BUILD_PATH}/${CMAKE_ANDROID_ARCH_ABI}/libadd.so DESTINATION ${CMAKE_CURRENT_SOURCE_DIR}/libs/${CMAKE_ANDROID_ARCH_ABI}) # 复制库文件
else ()
file(COPY ${SRC}/libadd.so DESTINATION ${CMAKE_CURRENT_SOURCE_DIR}/libs/${CMAKE_ANDROID_ARCH_ABI}) # 复制库文件
endif ()
file(COPY ${SRC}/libadd.h DESTINATION ${CMAKE_CURRENT_SOURCE_DIR}/src/main/jni) # 复制头文件
file(GLOB JNI_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/main/jni/*.c ${CMAKE_CURRENT_SOURCE_DIR}/src/main/jni/*.h) # 扫描jni目录下的头文件和库文件, 并设置给JNI_SRC
add_library(my_jni SHARED ${JNI_SRC}) # 添加jni中转库
file(GLOB OUTPUT_LIBRARY libs/${CMAKE_ANDROID_ARCH_ABI}/*.so) # 找到对应cpu的so库文件
target_link_libraries(
my_jni
${std-lib} # 连接android标准库给jni, 因为golang用到了一些标准库的定义
${OUTPUT_LIBRARY} # 连接给jni库
)
我在其中加入了详细的注释, 其中具体的 Cmake 语法没法展开讲
编写代码
C 代码
my_jni${CMAKE_CURRENT_SOURCE_DIR}/src/main/jni
src/main/jni
#include <jni.h>
#include "libadd.h"
//
// Created by jinglong cai on 2020/8/14.
//
JNIEXPORT jint JNICALL
Java_top_kikt_usegolibrary_JniLibrary_add(JNIEnv *env, jclass clazz, jint x, jint y) {
return add(x, y);
// return x + y;
}
JNIEXPORT jint JNICALL
Java_top_kikt_usegolibrary_JniLibrary_remove(JNIEnv *env, jclass clazz, jint x, jint y) {
return remove_int(x, y);
}
嗯, 其实就两个方法, 对应了 go 里定义的两个方法, 这里是 jni 的写法
Java 代码
JniLibrary.class
package top.kikt.usegolibrary;
public class JniLibrary {
static {
System.loadLibrary("my_jni");
}
public static native int add(int x, int y);
public static native int remove(int x, int y);
}
jni.h
MainActivity.kt
package top.kikt.usegolibrary
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kotlinx.android.synthetic.main.activity_main.*
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
textView.text = "come from jni ${JniLibrary.add(300, 150)}"
textView2.text = "come from jni ${JniLibrary.remove(300, 150)}"
}
}
就是简单的调用了这两个方法
运行
结果如下
后记
本篇为系列的第一篇, 不出意外, 后续应该会有对应的 iOS 篇, flutter-dart:ffi , wasm 篇则待定
以上