链接:https://pan.baidu.com/s/1zB9r5WwuTMIPNMlYl5HlvA
提取码:5ndl
在MainActivity中添加如下代码
可以发现,报红色,AndroidStudio希望我们继续创建sendIntArrayToJNI()的C++函数。
快捷生成对应的C++函数
鼠标放到红色上面:alt + enter
生成的C++函数如下
extern "C"
JNIEXPORT jstring JNICALL
Java_com_example_jnistudy_MainActivity_sendIntArrayToJNI(JNIEnv *env, jobject thiz,
jintArray int_array) {
// TODO: implement sendIntArrayToJNI()
}
这里对这部分代码再次说明下。
JNIEXPORT
这是一个固定的标识,表示当前这个函数可以被JNI框架调用
jstring
这是JNI的返回值的类型,这个类型和java的sendIntArrayToJNI返回值类型是对应的,如下
java中的sendIntArrayToJNI返回值类型是String,C++函数中的返回值类型也该是String,唯一区别是,在JNI里,String 是 用 jstring表示的。
假如,java中的sendIntArrayToJNI返回值类型是int,那么JNIEXPORT 后面就是jint ,在java里的每一个数据类型,在jni中都会有一个数据类型对应,如下是java和JNI 数据类型的对应表
JNICALL
这个是用于指定,C++函数中形参值的入栈顺序。以当前JNI函数sendIntArrayToJNI()为例,它有如下3个参数
这个函数的形参值入栈顺序有2种,一种是从右向左,一种是从左向右。
如何理解呢?
从右向左:就是JNI在调用sendIntArrayToJNI()时,会将传递给sendIntArrayToJNI()的形参值,先保存到栈里,保存的顺序就是从右开始,也就是从右边开始,依次将形参值,存放到栈里,sendIntArrayToJNI()在执行的时候,自己去这个栈里,按照顺序,自己去寻找对应的形参值。
从左向右:就是将形参值,从左边开始,依次存放到栈里。
这是一个固定的写法,各位采用默认的方式就行了。默认是从右向左将形参值放到栈里。
JNI函数的形参
生成的JNI函数,有3个形参
有2个是固定的,每个创建的JNI函数都会有,另一个参数是我们在java层定义的。
env
的值是JVM传递过来的,它代表的是当前JVM环境,它提供了很多功能的函数调用,具体后面再说。
thiz
代表的是JNI函数对应的java函数所在的类对象,有点绕扣,比如sendIntArrayToJNI()在MainActivity中定义的,那么这个
thiz就代表MainActivity这个对象
int_array
代表的就是java层sendIntArrayToJNI()的int[]
说了这么多,下面开始获取java传递过来的int[]
先在MainActivity中,添加如下代码
在JNI函数中获取传递过来的数组数据
1.获取数组指针的首地址
jintArray是一个class,它里面并没有提供任何方法,能够直接获取到数组中的元素,因此我们只能通过
env->GetIntArrayElements()来获取jintArray中所保存的数组元素的首地址。只要找到了首地址,我们就能以指针的形式,遍历数组了。
2.以指针的方式遍历数组
代码如下
想要遍历,首先就得获取数组的长度,env->GetArrayLength()就能获取到数组的长度。
现在基本已经完成了遍历的功能,现在我们来把结果输出来,验证下。
日志工具
在jni中,想要将结果打印出来,直接用print,肯定是不行的,需要用JNI中自带的日志函数
__android_log_print
使用这个函数,先要导入头文件
#include <android/log.h>
示例代码如下
这里说明下,__android_log_print 的形参
第一个参数:是日志的优先级,类似于Logcat中的日志级别
第二个参数,是日志的Tag,像java中的Log.e("JNI",“msg”)
第三个参数,就是具体要输出的内容,里面可以使用占位符
第四个参数:就是替换第三个参数中的占位符。
由于这个JNI函数,还有一个返回值,我们就随便返回一个内容吧
完整代码如下
extern "C"
JNIEXPORT jstring JNICALL
Java_com_example_jnistudy_MainActivity_sendIntArrayToJNI(JNIEnv *env, jobject thiz,
jintArray int_array) {
jint *javaArray = env->GetIntArrayElements(int_array, NULL);
int32_t length = env->GetArrayLength(int_array);
for (int k = 0; k < length; ++k) {
int tmp = *(javaArray+k);
__android_log_print(ANDROID_LOG_ERROR,"JNI","数组的值:%d",tmp);
}
std::string hello = "测试数组传递";
return env->NewStringUTF(hello.c_str());
}
现在程序就写好了,接下来就运行下吧