JNI挂接第三方so库

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 load(i,j);
    }
    public native long math(int i ,int j);
}

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

发布了1 篇原创文章 · 获赞 2 · 访问量 49

猜你喜欢

转载自blog.csdn.net/qq_28666281/article/details/105244948