C++编写、生成、调用so库详解(一)

开发中经常会用到so库,大多是调用第三方的so库,偶尔也需要自己封装一个so库给别人调用,这边就记录一下开发so库的一个过程.

首先我们这边是在Android Studio中开发的,所以仅描述在Android环境下开发过程,当然也可以用其他工具开发.

目录

1.第一步新建项目,配置需要的工具

2.新建C++文件,编写代码

3.so库的类型

4.打包非JNI标准so库

5.打包符合JNI标准so库

6.打包完成


1.第一步新建项目,配置需要的工具

我们就先新起一个项目,创建项目的时候选择Native C++选项,新建完成之后有些地方还需要手动配置一下,例如NDK.对于so库不了解的同学大多数应该都没有安装本地NDK.这边给大家看下怎么安装,

C++编写、生成、调用so库详解(一)_第1张图片

在settings中选择SDK选项,往下拉会有NDK的列表,在这边可以选择需要下载的NDK版本.

然后我们找到项目的local.properties文件,这边加上一行,我这边用的是20.1.5948944版本,至于各位自己用什么版本,按照自己刚刚安装的版本填写就可以了,路径是NDK的下载路径.

C++编写、生成、调用so库详解(一)_第2张图片

如果这项已经存在了就不需要手动添加了.

2.新建C++文件,编写代码

在src/main/cpp目录下新建C++文件

C++编写、生成、调用so库详解(一)_第3张图片

C++编写、生成、调用so库详解(一)_第4张图片

新建的时候最好加上头文件,后面会用到.

然后我们打开CMakeLists.txt文件,在add_library中添加我们刚刚新建的文件,只要加cpp文件就可以了(头文件不需要加)

这时候我们就可以开始编写C++代码了,我们就写个最简单的功能,两个整数求和.

C++编写、生成、调用so库详解(一)_第5张图片

这时我们so库中需要的功能已经写完了.

3.so库的类型

对于安卓开发而言,so库有两种,第一种是不符合JNI标准的so库,第二种是JNI标准的so库

先来解释下什么是JNI,JNI全名: Java Native Interface,意思是Java本地接口

Java本身是不可以直接调用C++代码的,需要依靠JNI来调用C++代码

两种有什么区别呢

第一种不符合JNI标准的,需要提供so库和对于的头文件,这种写的时候方便,调用起来麻烦.

第二种符合JNI标准的so库,写的时候麻烦,调用起来方便.

至于需要哪种,各位自己看着办

4.打包非JNI标准so库

这类so库需要生成两种文件,一个是so库,还有一个是头文件,就是把外界需要调用的函数名和类暴露出来.

如果是这种so库,我们现在就可以直接打包了

Android Studio左上角选择Build->Clean Project,先把项目生成的一些缓存文件清理一下,然后选择Rebuild Project,把项目重构一下

C++编写、生成、调用so库详解(一)_第6张图片

这时会看到多出来几个文件夹,我们打开build文件夹C++编写、生成、调用so库详解(一)_第7张图片

可以看到,在app->build->intermediates->cmake->debug->obj下有几个文件夹,这里面全是so库,这几个文件夹各不相同,可以全部复制过去,(如果不想全部复制,可以选择需要的ABI,怎么选择ABI?这个自己百度)

这边so库的名称和CmakeLists.txt中project("sodemo")是对应的.

注意,这类so库还需要头文件,要不然外面访问不到so库中的函数,头文件是哪个呢,就是这边的TestSo.h文件,直接复制出去即可.

C++编写、生成、调用so库详解(一)_第8张图片

总结一下就是需要给两类文件,一个是各个ABI对应的so库,一个就是头文件.

5.打包符合JNI标准so库

打包符合JNI标准的so库就有点麻烦了,需要自己手写JNI,

C++编写、生成、调用so库详解(一)_第9张图片

首先我们打开项目中自己生成的native-lib.cpp文件,这里面其实一开始是写了一个JNI函数的,我们可以依照那个写一个,

这边可以看到语法比较奇怪,我们挨个看一下

extern "C" JNIEXPORT jint JNICALL,这边是JNI固定语法,主要是jint,这个是就是我们返回的数据类型.

然后就是下面的函数名Java_com_example_sodemo_NativeTestSo_addition,这边com_example_sodemo就是包名,哪个的包名呢,就是NativeTestSo.java的包名,意思就是NativeTestSo.java这个类,要放在com/example/sodemo下面,这个是一定的,不能乱写

然后addition,这个就是NativeTestSo.java中对应的方法名,Java代码中调用的方法名

然后看到带了几个参数,JNIEnv *env, jobject , jint num1,jint num2,前两个JNIEnv *env, jobject是固定的,不用管,主要看后面两个,这两个就是NativeTestSo.java中addition方法传进来的两个参数.

简单组合一下就是

extern "C" JNIEXPORT 返回数据类型 JNICALL Java_包名_类名_方法名(JNIEnv *env, jobject,形参1,形参2...){}

然后按照上面打包so库的步骤执行一下,在app->build->intermediates->cmake->debug->obj就会出现直接可以用的so库了

6.调用

有一种额外的情况,就是我这的这段C++代码,不需要打包成so库给别人用,只在这个项目中使用

这时候就不需要像上面一样去打包so库了,直接新建一个Java类

C++编写、生成、调用so库详解(一)_第10张图片

这边注意看圈红的地方,全都是上文中第5条里提到的注意点,一个字母都不能错,我这边的包名和类目都是前面一篇中指定的,各位要替换成自己的

然后就可以直接调用啦

C++编写、生成、调用so库详解(一)_第11张图片

可以看到,我这边已经调用成功了.

7.下一篇,调用so库

C++编写、生成、调用so库详解(二)

你可能感兴趣的:(Android,c++,so库,JNI,Android)