JNI 取用 Java 数组
即将已经在Java中产生的数组数值传递到native去处理并返回Java层处理结果,==不会修改Java中该数组Field的数值==,比如应用场景:
- Java层通过Camera获取的帧数据传递给native结合opencv进行处理,并返回(图像预处理/检测/分类等)结果;
- 在Java业务层产生的数据,需要进行复杂的运算(比如加密/解密等);
- ……
此类场景一般需要将数组(或者其他形式的数据结构)对象通过调用native方法时作为参数将其由上层Java业务层传递到JNI层;
JNI 修改 Java 数组
即数据全部是由JNI层产生的,而Java层有对应的数据结构进行被动更新,在Java层不具备赋值动作,全部的赋值动作已在JNI完成,在JNI层通过反射回调的方式进行被动更新,==会修改Java中该数组Field的数值==,比如应用场景:
- Java业务层通过Camera获取帧数据,其业务目的是为了实现人脸检测,人脸结构在Java有对应的类结构(比如包含特征点/性别/微笑/睁眼等),在JNI执行该函数过程中,即完成更新(为什么不返回这个人脸结构体?因为我们可能更需要这个函数执行成功与否的状态等信息);
- 其他需要在JNI就完成Java层field的更新业务……
此类场景一般需要在JNI通过反射调用其构造函数创建实例并赋值,然后再设置回Java对应的Field;
JNI 取用 Java 数组
在JNI中获取在Java中已经有值的数组使用,赋值逻辑已在Java中完成。
获取Java的byte数组
在Java中存在byte数组datas并且有值,JNI获取该值后在native层使用。因为datas属于实例变量,此时Java层需将JavaCodeClass的实例作为参数传入。
//Java code
package com.riskycheng.test;
public class FaceInfo{
private String id;
private byte[] datas;
private String[] dataStrs;
private float[] floatArray;
private int[] intArray;
private long[] longArray;
private PoseInfo[] poseInfos;
private PoseInfo curPose;
}
//native code
nTest(JNIEnv *jenv, jobject obj, jobect faceInfo){
//获取实例
jclass cls_JavaCodeClass = jenv->FindClass("com/riskycheng/test/FaceInfo");
//获取field
jfieldID jid_datas = jenv->GetFieldID(cls_JavaCodeClass,"datas","[B");
//根据field获取实例中的成员变量
jbyteArray modelBytesArray = (jbyteArray)jenv->GetObjectField(faceInfo,jid_datas);
//将数值进行转化使用
jboolean isCopy = false;
uint8_t *dataNatives = (uint8_t*)jenv->GetByteArrayElements(modelBytesArray, &isCopy);
//注意内存管理
//...delete[] dataNatives;
}
获取Java的String数组
//Java code
package com.riskycheng.test;
public class FaceInfo{
private String[] datas;
//...对datas有赋值操作
}
//native code
nTest(JNIEnv *jenv, jobject obj, jobect faceInfo){
//获取实例
jclass cls_FaceInfo = jenv->FindClass("com/riskycheng/test/FaceInfo");
//获取field
jfieldID jid_datas = jenv->GetFieldID(cls_FaceInfo,"datas","[Ljava/lang/String;");
//根据field获取实例中的成员变量
jobjectArray stringArray = (jobjectArray)jenv->GetobjectArray(faceInfo, jid_datas);
//还可以获取该数组的长度
jint length = jenv->GetArrayLength(stringArray);
//可以取值使用
char* str = new char[100]();
for(int i = 0; i < length; i++){
jstring jstring1 = (jstring)env->GetObjectArrayElement(stringArray,i);
char* data = strdup(env->GetStringUTFChars(jstring1,NULL));
sprintf(results,"%s%s",results,data);
delete[] data;
env->DeleteLocalRef(jstring1);
}
env->DeleteLocalRef(stringArray);
env->DeleteLocalRef(cls_FaceInfo);
return env->NewStringUTF(results);
}
获取Java的Float数组
//Java code
package com.riskycheng.test;
public class FaceInfo{
private float[] floatArray;
//...对floatArray有赋值操作
}
//native code
nTest(JNIEnv *jenv, jobject obj, jobect faceInfo){
jclass cls_FaceInfo = env->FindClass("com/riskycheng/test/FaceInfo");
jfieldID datafloatsId = env->GetFieldID(cls_FaceInfo,"floatArray","[F");
jfloatArray jfloatArray1 = (jfloatArray)env->GetObjectField(faceInfo,datafloatsId);
jboolean isCopy = static_cast<jboolean>(false);
jfloat* nativeFloatArray = env->GetFloatArrayElements(jfloatArray1,&isCopy);
jint length = env->GetArrayLength(jfloatArray1);
char *data = new char[100]();
for (int i = 0; i < length; ++i) {
sprintf(data,"%s + %f",data, nativeFloatArray[i]);
}
env->DeleteLocalRef(cls_FaceInfo);
env->ReleaseFloatArrayElements(jfloatArray1,nativeFloatArray,JNI_ABORT);
env->DeleteLocalRef(jfloatArray1);
return env->NewStringUTF(data);
}
获取Java的int数组
//Java code
package com.riskycheng.test;
public class FaceInfo{
private int[] intArray;
//...对intArray有赋值操作
}
//native code
nTest(JNIEnv *jenv, jobject obj, jobect faceInfo){
jclass cls_FaceInfo = env->FindClass("com/riskycheng/test/FaceInfo");
jfieldID dataintsId = env->GetFieldID(cls_FaceInfo,"intArray","[I");
jintArray jintArray1 = (jintArray)env->GetObjectField(faceInfo, dataintsId);
jboolean isCopy = static_cast<jboolean>(false);
jint * nativeIntArray = env->GetIntArrayElements(jintArray1,&isCopy);
jint length = env->GetArrayLength(jintArray1);
char *data = new char[100]();
for (int i = 0; i < length; ++i) {
sprintf(data,"%s + %d",data, nativeIntArray[i]);
}
env->DeleteLocalRef(cls_FaceInfo);
env->ReleaseIntArrayElements(jintArray1,nativeIntArray,JNI_ABORT);
env->DeleteLocalRef(jintArray1);
return env->NewStringUTF(data);
}
获取Java的long数组
//Java code
package com.riskycheng.test;
public class FaceInfo{
private long[] longArray;
//...对longArray有赋值操作
}
//native code
nTest(JNIEnv *jenv, jobject obj, jobect faceInfo){
jclass cls_FaceInfo = env->FindClass("com/riskycheng/test/FaceInfo");
jfieldID datalongsId = env->GetFieldID(cls_FaceInfo,"longArray","[J");
jlongArray jlongArray1 = (jlongArray)env->GetObjectField(faceInfo, datalongsId);
jboolean isCopy = static_cast<jboolean>(false);
jlong * nativeLongArray = env->GetLongArrayElements(jlongArray1,&isCopy);
jint length = env->GetArrayLength(jlongArray1);
char *data = new char[100]();
for (int i = 0; i < length; ++i) {
sprintf(data,"%s + %ld",data, nativeLongArray[i]);
}
env->ReleaseLongArrayElements(jlongArray1,nativeLongArray,JNI_ABORT);
env->DeleteLocalRef(jlongArray1);
env->DeleteLocalRef(cls_FaceInfo);
return env->NewStringUTF(data);
}
获取Java的boolean数组
//Java code
package com.riskycheng.test;
public class FaceInfo{
private boolean[] booleansArray;
//...对booleansArray有赋值操作
}
//native code
nTest(JNIEnv *jenv, jobject obj, jobect faceInfo){
jclass cls_FaceInfo = env->FindClass("com/riskycheng/test/FaceInfo");
jfieldID dataBoolsId = env->GetFieldID(cls_FaceInfo,"booleansArray","[Z");
jbooleanArray jboolArray1 = (jbooleanArray)env->GetObjectField(faceInfo, dataBoolsId);
jboolean isCopy = static_cast<jboolean>(false);
jboolean * nativeBoolArray = env->GetBooleanArrayElements(jboolArray1,&isCopy);
jint length = env->GetArrayLength(jboolArray1);
char *data = new char[100]();
for (int i = 0; i < length; ++i) {
sprintf(data,"%s + %s",data, nativeBoolArray[i] ? "true" : "false");
}
env->ReleaseBooleanArrayElements(jboolArray1,nativeBoolArray,JNI_ABORT);
env->DeleteLocalRef(jboolArray1);
env->DeleteLocalRef(cls_FaceInfo);
return env->NewStringUTF(data);
}
获取Java的自定义数组
//Java code
package com.riskycheng.test;
public class FaceInfo{
private PoseInfo[] poseInfoArray;
//...对poseInfoArray有赋值操作
}
//Java code
package com.riskycheng.test;
public class PoseInfo{
private String name;
private int id;
public PoseInfo(String name, int id){
this.name = name;
this.id = id;
}
}
//native code
nTest(JNIEnv *jenv, jobject obj, jobect faceInfo){
jclass cls_FaceInfo = env->FindClass("com/riskycheng/test/FaceInfo");
jfieldID dataPoseInfosId = env->GetFieldID(cls_FaceInfo,"poseInfos","[Lcom/riskycheng/test/PoseInfo;");
jobjectArray nativePoseInfoArray = (jobjectArray)env->GetObjectField(faceInfo, dataPoseInfosId);
jint length = env->GetArrayLength(nativePoseInfoArray);
LOGD("length %d", length);
char *data = new char[100]();
for (int i = 0; i < length; ++i) {
jobject poseInfo = env->GetObjectArrayElement(nativePoseInfoArray,i);
//我们需要在此获取其类型并用于后续查找其Fields
jclass cls_PoseInfo = env->GetObjectClass(poseInfo);
jfieldID jidPoseInfo_name = env->GetFieldID(cls_PoseInfo,"name","Ljava/lang/String;");
jfieldID jidPoseInfo_id = env->GetFieldID(cls_PoseInfo,"id","I");
jstring name = (jstring)env->GetObjectField(poseInfo,jidPoseInfo_name);
jint id = env->GetIntField(poseInfo,jidPoseInfo_id);
char *nameStr = jstringToChar(env, name);
sprintf(data, "%s + %s%d", data, nameStr, static_cast<int>(id));
env->DeleteLocalRef(poseInfo);
delete[] nameStr;
env->DeleteLocalRef(cls_PoseInfo);
}
env->DeleteLocalRef(nativePoseInfoArray);
env->DeleteLocalRef(cls_FaceInfo);
return env->NewStringUTF(data);
}
JNI 修改 Java 数组
在JNI中获取在Java中的数组Field并进行修改。(未完待续)