接着上一个例子java 调用本地代码 继续补充代码,这次看看本地代码如何接收java层数组。
首先在MainActivity.java 添加如下代码声明
public native void stringArray(String []strArr);
public native void floatArray(float []fArray);
public native void boolArray(boolean[] bArray);
native关键字会告诉编译器这是一个本地方法,不需要检查该方法的在java层的实现。进入项目根目录然后执行如下命令进入目标目录(我用的是Ubuntu系统,所以用的cd命令,其他系统进入相应目录并在该目录开一个终端即可)
cd app/src/main/java
javah 生成header文件
javah -jni com.example.test.jnitest.MainActivity
执行后在同级目录下会生成一个后缀名为.h的文件
将这个文件移到到cpp文件夹下,将.h后缀名改为.cpp ,并将内容的函数声明改为函数定义即
JNIEXPORT jstring JNICALL Java_com_example_test_jnitest_MainActivity_stringFromJNI
(JNIEnv *, jobject){
}
JNIEXPORT void JNICALL Java_com_example_test_jnitest_MainActivity_stringArray
(JNIEnv *, jobject, jobjectArray){
}
JNIEXPORT void JNICALL Java_com_example_test_jnitest_MainActivity_floatArray
(JNIEnv *, jobject, jfloatArray){
}
JNIEXPORT void JNICALL Java_com_example_test_jnitest_MainActivity_boolArray
(JNIEnv *, jobject, jbooleanArray){
}
然后在函数定义内实现相应的逻辑,先拿
JNIEXPORT void JNICALL Java_com_example_test_jnitest_MainActivity_stringArray
(JNIEnv *, jobject, jobjectArray){}
为例,先为函数添加型参
JNIEXPORT void JNICALL Java_com_example_test_jnitest_MainActivity_stringArray
(JNIEnv *env, jobject object, jobjectArray stringArray){
}
然后获取string数组本地缓存,string 是一个对象类型,所以要用GetObjectArrayElement获取所对应的本地引用,在jni开发中会遇到多种GetXXXElement(XXX代表数据类型),他的作用是或去Java数据的本地引用与之对应的就是ReleaseXXX,他的作用是把本地数据反射给java,具体怎么实现的以后在做探究,这里先提一下。通过GetObjectArrayElement获取完数据后,需要将数据打印出来用以证明获取是否正确,打日志很简单,直接使用android的log系统即可,首先引入log头文件
#include
然后在全局的地方写一个宏方便调用,也可以不写宏
#define LOG(...) __android_log_print(ANDROID_LOG_INFO,"jnitest",__VA_ARGS__ )
这个版本的androidstudio已经在cmakelist里添加了log的库,所以不需要修改cmakelist.txt,在函数实现上直接调用即可,函数实现代码如下
JNIEXPORT void JNICALL Java_com_example_test_jnitest_MainActivity_stringArray
(JNIEnv *env, jobject object, jobjectArray stringArray) {
int count = env->GetArrayLength(stringArray);
for (int i = 0; i < count; i++) {
jobject item = env->GetObjectArrayElement(stringArray, i);
const char *str = env->GetStringUTFChars((jstring) item, 0);
LOG("index:%d string:%s", i, str);
env->ReleaseStringUTFChars((jstring) item, str);
}
}
本例中java层是这样调用的
stringArray(new String[]{"A","B","C","D","E","F","G"});
运行结果
07-18 15:03:00.351 4425-4425/com.example.test.jnitest I/jnitest: index:0 string:A
index:1 string:B
index:2 string:C
index:3 string:D
index:4 string:E
index:5 string:F
index:6 string:G
获取float等基本类型的数据相较于string这样对象数组更简单些,这里只拿float数组为例,代码如下
JNIEXPORT void JNICALL Java_com_example_test_jnitest_MainActivity_floatArray
(JNIEnv *env, jobject, jfloatArray floatArray){
jfloat * array = env->GetFloatArrayElements(floatArray,0);
int count = env->GetArrayLength(floatArray);
for(int i=0;iReleaseFloatArrayElements(floatArray,array,0);
}
知道了以上几种方法就可以轻松获取java层的数据了