https://blog.csdn.net/minwenping/article/details/122117169
我是按照上面博主的分享尝试的,现记录一下自己遇到的问题。
- 我调试cmake 版本 VERSION 3.22.1
- 使用博主分享的 VERSION 3.18前的方法,可行;
- 补充两点:
3.1 注意引入的库路径路径: $ {CMAKE_SOURCE_DIR}/…/…/…/libs/arm64-v8a/libchip.so
宏需要加$ ,以及目录层级;
3.2 build.gradles 需要指定ndk 描述库所对应的架构,注与路径中的arm64-v8a对应;
defaultConfig {
applicationId "com.example.easttest"
minSdk 28
targetSdk 33
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
ndk{
abiFilters 'arm64-v8a'
}
}
否则会报,默认会编译四个架构(x86,x86-64,arm64-v8,armeabi-v7a)
cmd.exe /C "cd . && D:\worktool\androidsdk\ndk\25.1.8937393\toolchains\llvm\prebuilt\windows-x86_64\bin\clang++.exe --target=aarch64-none-linux-android28 --sysroot=D:/worktool/androidsdk/ndk/25.1.8937393/toolchains/llvm/prebuilt/windows-x86_64/sysroot -fPIC -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -fno-limit-debug-info -static-libstdc++ -Wl,--build-id=sha1 -Wl,--no-rosegment -Wl,--fatal-warnings -Wl,--gc-sections -Wl,--no-undefined -Qunused-arguments -shared -Wl,-soname,librenforlib_1.so -o C:\Users\shxy\AndroidStudioProjects\renforlib_1\app\build\intermediates\cxx\Debug\6f2b6623\obj\arm64-v8a\librenforlib_1.so CMakeFiles/renforlib_1.dir/native-lib.cpp.o C:/Users/shxy/AndroidStudioProjects/renforlib_1/app/src/main/cpp/../../../libs/armeabi-v7a/libchip.so D:/worktool/androidsdk/ndk/25.1.8937393/toolchains/llvm/prebuilt/windows-x86_64/sysroot/usr/lib/aarch64-linux-android/28/liblog.so -latomic -lm && cd ."
ld: error: C:/Users/shxy/AndroidStudioProjects/renforlib_1/app/src/main/cpp/../../../libs/arm64-v8a/libchip.so is incompatible with armelf_linux_eabi
3.3 如果路径中使用${ANDROID_ABI},则ndk需要含有四种架构,且libs目录下也要有四种对应的库。
3.4 GRADLE_USER_HOME = C:\Users\shxy**.gradle**
3.5 android studio 工程路径不能有中文
3.6 编译工程选择语言Kotlin和java,编出来的C++库不能通用(java编译的只能在java工程调用,kotlin编译的只能在kotlin工程调用)。
Java:
static {
System.loadLibrary("test3");
}
Kotlin:
companion object {
// Used to load the 'test3' library on application startup.
init {
System.loadLibrary("test3")
}
}
Java调用so(Kotlin工程编译)错误如下:
2024-08-01 16:11:54.832 7615-7615 AndroidRuntime com.example.renforlib E FATAL EXCEPTION: main
Process: com.example.renforlib, PID: 7615
java.lang.UnsatisfiedLinkError: dlopen failed: cannot locate symbol "chip_init" referenced by "/data/app/~~-QsN2xqCdQqmNHwFee_1tQ==/com.example.renforlib-iaJo_VsTdzuarjYJQsJCIw==/base.apk!/lib/arm64-v8a/librenforlib.so"...
at java.lang.Runtime.loadLibrary0(Runtime.java:1087)
at java.lang.Runtime.loadLibrary0(Runtime.java:1008)
at java.lang.System.loadLibrary(System.java:1664)
at com.example.renforlib.MainActivity.<clinit>(MainActivity.java:18)
at java.lang.Class.newInstance(Native Method)
at android.app.AppComponentFactory.instantiateActivity(AppComponentFactory.java:95)
at androidx.core.app.CoreComponentFactory.instantiateActivity(CoreComponentFactory.java:45)
at android.app.Instrumentation.newActivity(Instrumentation.java:1253)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3388)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3648)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:85)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2116)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:223)
at android.app.ActivityThread.main(ActivityThread.java:7723)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:612)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:997)
总结:以上只是会为了调试结果而写的记录,没有仔细分析原理。
Android Studio 最新版与Android Studio 2022 区别:
- setting.gradle.kts 与 setting.gradle
添加镜像
最新版:
maven { setUrl("https://maven.aliyun.com/repository/gradle-plugin") }
2022:
maven { url 'https://maven.aliyun.com/repository/gradle-plugin' }
- build.gradle.kts 与 build.gradle
最新版:
id("com.android.application") version "8.0.0" apply false
2022:
id 'com.android.application' version '8.0.0' apply false
- app/build.gradles.kts 与app/build.gradles
最新版:
ndk{
abiFilters.addAll(arrayOf("arm64-v8a"))
}
2022:
ndk{
abiFilters 'arm64-v8a'
}
注:
- 使用C++去写一个动态库,由于C++编译器对于函数的符号的生成需要进行名字修饰处理,然后生成的函数符号不再跟源代码中定义的函数名一致;
- JVM调用的native接口/接口导致通过函数名去调用函数时(用函数名充当函数符号去查找函数地址),将会找不到具体的实现,然后崩溃;
- 所以使用C++去写navtive的接口时,需要用extern “C” 包住native接口,这样就显示告诉C++编译器,对于我们的接口/函数使用C语言的方式(函数符号即函数名称)去编译代码和生成函数符号。
- 由于JNI native_lib.cpp由C++编译器并编译,需要在库的头文件加上extern "C"声明,保证编译时函数名与源代码一致。
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif /* __cplusplus */
......
int chip_init();
......
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif /* __cplusplus */