Android NDK - JNI 与 Java 接收及修改数组

14 篇文章 0 订阅
14 篇文章 0 订阅

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并进行修改。(未完待续)

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值