android开发中使用JNI调用本地函数要注意的一些问题

首先我们要知道什么是JNI,什么情境下会用到JNI。

先简单地说一下什么是JNI: 

JNI(Java Native Interface)

       1、什么是JNI:
              JNI(Java Native Interface):java本地开发接口
              JNI是一个协议,这个协议用来沟通java代码和外部的本地代码(c/c++)
              外部的c/c++代码也可以调用java代码
       2、为什么使用JNI
              效率上 C/C++是本地语言,比java更高效
              代码移植,如果之前用C语言开发过模块,可以复用已经存在的c代码
              java反编译比C语言容易,一般加密算法都是用C语言编写,不容易被反编译
       3、Java基本数据类型与C语言基本数据类型的对应
              
       3、引用类型对应
              
       4、堆内存和栈内存的概念
              栈内存:系统自动分配和释放,
                      保存全局、静态、局部变量,
                      在站上分配内存叫静态分配,
                      大小一般是固定的
              堆内存:程序员手动分配(malloc/new)和释放(free/java不用手动释放,由GC回收),
                      在堆上分配内存叫动态分配,
                      一般硬件内存有多大堆内存就有多大


那么在什么情景下我们会用到呢,我之前在做安卓开发时,需要用手机去识别某些情景下的图片。在图像的处理上我们更多地会用到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>中的一些方法去把参数里面的内存取出来放到一个重新申请的连续的内存块中,然后在新的内存块上进行操作。 为了避免内存泄漏,我们要注意这部分内存的申请和释放。

目前我做的项目中,大概就遇到了这样的一些情况,后续如果有更多问题我会再补上。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值