JNI挂接第三方so库

Karima ·
更新时间:2024-11-10
· 734 次阅读

JNI挂接第三方so库(androidstudio)

最近在做一个项目,需要挂接其它部门提供的so库,android纯小白,在网上找了一堆资料,走了很多弯路终于初步挂接成功,整个流程给大家分享一下

基本工具

androidstudio,google官方提供的开发工具,迭代了很多版本了,确实有很多弊端,但是开发用起来的确顺手许多。

基本基础

由于挂接的so库是c++编译的,需要c++基础,JNI的基本知识也要懂些,不懂的童鞋可以去查其他资料,不需要学多深,jni的内存机制、类型转换学懂了就差不多了。

第一步 建立项目

在androidstudio里建立一个Native C++项目,没错,androidstudio自带示例。

第二步 编写CMkelist

androidstudio的目录结构这里就不多讲了,打开main-cpp目录下一个叫CMakelist的文件,androidstduio将所有的负责操作流程都浓缩在这个txt文件里面了,没多少复杂的工作,只要按照固定的格式填写,androidstudio就会自动执行命令,生成so文件链接动态静态库。

add_library( # Sets the name of the library. native-lib # Sets the library as a shared library. SHARED # Provides a relative path to your source file(s). native-lib.cpp )

这是你自己生成的so库,这里没什么可以修改的地方,native-lib.cpp是你自己编译的cpp文件,涉及到第三方库的调用都在这里面,这也是为什么android编程需要c++基础的原因。

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 )

这段也没什么好说的,无需修改,这里是定位lib的位置。
接下来是我们自己需要添加的

target_include_directories(native-lib PRIVATE ${CMAKE_SOURCE_DIR}/include )

这段是添加头文件,并告知工程头文件的位置。

add_library( # Sets the name of the library. abc # Sets the library as a shared library. SHARED # Provides a relative path to your source file(s). IMPORTED) set_target_properties(abc PROPERTIES IMPORTED_LOCATION ${PROJECT_SOURCE_DIR}/../jniLibs/${ANDROID_ABI}/libabc.so)

addlibrary添加第三方库,并告知第三方库的类型,SHARED是静态库,STATIC是静态库。
set_target_properties是告知第三方库的位置,${ANDROID_ABI}是自动获取手机的架构,如arm64-v8a。
如何需要导入多个第三方库,就按照add_library()、set_target_properties()继续添加即可。

target_link_libraries( # Specifies the target library. native-lib abc abc1 abc2 # Links the target library to the log library # included in the NDK. ${log-lib} )

最后一个target_link_libraries(),将所有的第三方库连接到我们自己的native-lib库上。

第三步 编译native-lib.cpp文件

在这里我们将第三方的头文件导入进来,就可以调用第三方的方法了。

int sum(int i,int j) { return i+j; }

例如第三方库中有这样一个函数,我们想把它封装成java的函数

extern "C" JNIEXPORT jint JNICALL Java_com_example_test_math_sum(JNIEnv* env,jobject /* this */,jint i ,jint j) { jint sum_ = i+jj return sum_; }

JNI函数规范是这样定义的,函数名是由包名+类名+函数名构成的,传入的参数必须是jni类型的,同时返回的参数也必须是jni类型的,由于int和jint可以直接转换,所以函数中省略了类型转换的过程。

package com.example.test; public class math{ static { System.loadLibrary("native-lib"); } public int java_math(int i,int j) { return math(i,j); } public native long math(int i ,int j); }

同时在我们的java中也要有对应的类和对应的函数,这样一个简单的由C++实现的java的math()函数就封装好了。


作者:qq_28666281



jni

需要 登录 后方可回复, 如果你还没有账号请 注册新账号
相关文章