CMake方式调用第三方so
- 背景
- CMake工程配置
- 工程配置
- 配置CMakeLists.txt
- 配置build.gradle
- 调用第三方so中的方法
背景
最近一个项目是对接自研团队的个so库,因为之前都是用ndk来编译自己的so库,一直没有问题,但是用到这个自研的的so库一直有问题,调用不了里面的方法;原因就是:第三方提供的so库以及头文件都没有没有引入jni.h头文件。所以我们在导入第三方so库以及头文件的时候需要手动的将其关联到自己的so库中,关联成功后就可以在native库中include进第三方头文件,引进头文件成功后就可以在自定义的JNI接口中对第三方头文件中内容进行调用。
所以就尝试用CMake的方式来加载。
建议大家还是用CMake的方式来进行JNI开发,因为CMake是跨平台的构建工具,对JNI开发来说比较明显的优点就是:1,编写c代码有提示;2,自动搜索正在构建的软件可能需要的程序、库和头文件的能力;3,能够为自动生成的文件创建复杂的自定义命令;其他的高级特性可自行搜索;
CMake工程配置
工程配置
1,android studio新建个新工程,不过多说明了;
2,新建java文件testJni.java,随便哪个目录
private native int sayHello(String text);
生成.h文件,可用参考 JNI生成so,然后把.h文件拷贝到jni(自己创建)目录下,如图:
新增文件夹,用来存放要导入的第三方so库以及头文件
第三方so库:放在src/main/libs/${ANDROID_ABI}(对应的CPU架构)/你的第三方so库
第三方头文件:放在src/main/jni/你的第三方头文件
如图:
注意以下几点:
1)libs、CPU对应的架构文件夹(如上图的arm64-v8a)、jin都是我自己创建的;
2)CPU对应的架构文件夹可以根据自己需要来声明,因为提供给我的第三方so库只支持arm64-v8a,所以这里我只创建了arm64-v8a文件夹,通常来说,如果第三方支持什么CPU架构,就创建对应的架构文件夹(armeabi-v7a、arm64-v8a、x86、x84_64),然后把对应的so库放到对应的架构文件夹中;
3)这里的第三方so库以及头文件的存放位置只是我自己的习惯,并不是一定要按我这样放,你可以定义自己的存放路径,但是这个路径你要记住,在后面配置 CMakeLists.txt 中会用到。
配置CMakeLists.txt
app目录下新建空文件CMakeLists.txt
修改CMakeLists.txt,关联第三方头文件到native so,配置好第三方so库以及头文件导入的路径
#指定CMake构建本地库时所需的最小版本
cmake_minimum_required(VERSION 3.18.1)
# 指定编译出来的so库的存放位置,方便取用给其他开发者,如果指定到jniLibs下需要在build.gradle中配置编译优先解决冲突问题。
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/src/main/libs/${ANDROID_ABI})
set(LIB_DIR "${CMAKE_SOURCE_DIR}/src/main/libs") # 第三方库的存放路径,命名为LIB_DIR,下面会用到
file(GLOB source src/main/jni/testjni.cpp)
add_library( # Sets the name of the library. 将资源文件生成动态链接库(so文件)的库名称(文件名称:“lib" +设置的名称)
test_jni
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).资源文件(C或C++)的相对位置
${source}
)
target_include_directories(test_jni
PRIVATE
${PROJECT_SOURCE_DIR}/src/main/jni)
add_library(fronted
SHARED IMPORTED)
set_target_properties(fronted
PROPERTIES IMPORTED_LOCATION
${LIB_DIR}/${ANDROID_ABI}/libfronted.so) # 指定第三方库的位置、链接
find_library( # Sets the name of the path variable.
log-lib
# Specifies the name of the NDK library that
# you want CMake to locate.
log )
target_link_libraries( # Specifies the target library.将所有的add_library中的库链接起来,有多少个add_library成的库就将其添加到这里
test_jni #这个和add_library中的指定的so库名称一致
fronted
# lib-add
# Links the target library to the log library
# included in the NDK.
${log-lib} )
第三方so名称是libfronted.so,注意make文件中的用法及定义,里面有相应的注释,需要注意的地方如图
配置build.gradle
注意是app下的build.gradle
android {
compileSdk 32
defaultConfig {
applicationId "com.zeekr.zeekrmake"
minSdk 21
targetSdk 32
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
externalNativeBuild{
cmake{
cppFlags ""// 设置c++标准为默认
abiFilters "arm64-v8a"
}
}
ndk {// 可以不配置
moduleName "test_jni" // ndk模块名字
abiFilters "arm64-v8a"// 不配置的话,默认生成所有平台的so
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
externalNativeBuild{
cmake{
// version '3.10.2'
path "CMakeLists.txt"// 指定CMake文件的位置
}
}
buildFeatures {
viewBinding true
}
}
配置完成后make project;
调用第三方so中的方法
没有错误,说明配置成功,就可以引入自研so库中的.h文件了,然后调用其中的方法了;
make project就可用生成so库了,目录在makefile文件中定义有;
这篇文章就介绍到这里,喜欢的点赞求关注。