android开发中使用JNI调用本地函数要注意的一些问题
首先我们要知道什么是JNI,什么情境下会用到JNI。
先简单地说一下什么是JNI:
JNI(Java Native Interface)
那么在什么情景下我们会用到呢,我之前在做安卓开发时,需要用手机去识别某些情景下的图片。在图像的处理上我们更多地会用到openCV这个库,虽然openCV在java层也有库,但是里面很多函数在C++层集成得更好,一些矩阵运算和变换运算在c++层也更加高效,因此我们这里会选择在Java开发时去调用我们在c++层已经写好的函数。
首先一个本地函数在java层需要用关键字 native 来修饰。然后在对应的build.gradle和.xml文件中写明依赖关系,即本地c++代码的位置(不过实际上这部分操作我们一般很少自己去完成,用AndroidStudio等IDE会帮我们处理好)。 然后我们需要把要写的函数在c++层的.h中注册,这里需要引进 <jni.h> ,注意这里并不能只是像朴素的c++函数那样只写一个函数名去注册。需要有签名(其实就是在函数名的基础上加一些前后缀,具体的规则下面会有),这些签名跟函数所在的包名和其传入的参数有关。
上图简单地介绍了有关AndroidJni签名的一些规则,更加具体仔细的大家可以查阅一些官方的API文档。接下来我们把这个在.h文件中注册的函数在.cpp中实现。当然,在开始实现函数之前,还有些比较细枝末叶的命名规则和函数名写法,这里不多展开,可以在Android官方的开发者文档中看到。
在函数的实现过程中,同时还要注意些细节的问题。比如内存的申请和释放,因为从java层传过来的参数的内存不一定是连续的,我们要用到c++层<jni.h>中的一些方法去把参数里面的内存取出来放到一个重新申请的连续的内存块中,然后在新的内存块上进行操作。 为了避免内存泄漏,我们要注意这部分内存的申请和释放。
目前我做的项目中,大概就遇到了这样的一些情况,后续如果有更多问题我会再补上。