我正在尝试将jfloatArray中的某些值返回到Java Android代码之前。
我发现我不能使用常规方法newArray[i] = result[i];来代替它,而应该使用env->SetFloatArrayElement(newArray,i,result[i]);

问题在于此函数引发错误:


  [armeabi-v7a]编译++臂:tensorflow_mnist   jni /./ tensorflow_jni.cc:在函数'_jfloatArray *
  Java_jp_narr_tensorflowmnist_DigitDetector_detectDigit(JNIEnv *,
  jobject,jintArray)':jni /./ tensorflow_jni.cc:171:14:错误:“ JNIEnv”
  没有名为“ SetFloatArrayElement”的成员
           env-> SetFloatArrayElement(newArray,i,result [i]);
                ^


码:

JNIEXPORT jfloatArray JNICALL
TENSORFLOW_METHOD(detectDigit)(JNIEnv* env, jobject thiz, jintArray raw_pixels) {

    jboolean iCopied = JNI_FALSE;
    jint* pixels = env->GetIntArrayElements(raw_pixels, &iCopied);
    jfloatArray newArray = env->NewFloatArray(2);
    jfloat *result = process( reinterpret_cast<int*>(pixels) );


    for(int i=0; i<2; ++i) {

        //VLOG(0) <<  " (" << i << "): " << newArray[i];
        //newArray[i] = result[i];
        //env->SetFloatArrayElement(newArray,i,result[i]);
     }


    env->ReleaseIntArrayElements(raw_pixels, pixels, JNI_ABORT);
    env->ReleaseFloatArrayElements(newArray, result, JNI_ABORT);

    free(result);

    return newArray;
}

最佳答案

我正在尝试将jfloatArray中的某些值返回到Java Android代码之前。我发现我不能使用常规方法newArray[i] = result[i];来代替它,而应该使用env->SetFloatArrayElement(newArray,i,result[i]);


什么让你有那个想法?正如编译器告知您的那样,JNI没有SetFloatArrayElement()函数。仅对Object数组(即SetObjectArrayElement())有一个单一元素设置功能。

处理原始数组有几种选择。


经典的机制是使用适当的Get*ArrayElements()函数获取普通数组,先修改数组,然后再ReleaseArrayElements()。还要注意,使用这种方法,如果要提交更改(如您所做的那样),则必须使用模式0JNI_COMMIT,而不是JNI_ABORT
对于诸如快速调用之类的不调用其他JNI函数的用法,可以考虑使用GetPrimitiveArrayCritical()ReleasePrimitiveArrayCritical()。但是,如果在get和release之间进行任何I / O操作,则不应这样做。
但是,对于您的特定情况,我建议使用SetFloatArrayRegion()。有一个相应的GetFloatArrayRegion(),但是您不需要它,因为您不必担心固定或(Java)数组元素的初始值。


使用第三个替代方法可能如下所示:

JNIEXPORT jfloatArray JNICALL
TENSORFLOW_METHOD(detectDigit)(JNIEnv* env, jobject thiz, jintArray raw_pixels) {

    jfloatArray newArray = env->NewFloatArray(2);
    jint* pixels = env->GetIntArrayElements(raw_pixels, NULL);

    jfloat *result = process( reinterpret_cast<int*>(pixels) );

    env->ReleaseIntArrayElements(raw_pixels, pixels, JNI_ABORT);
    env->SetFloatArrayRegion(newArray, 0, 2, result);

    free(result);

    return newArray;
}


如果您可以依靠process()函数非常快速地运行并且没有任何阻塞的可能性,则可以考虑使用GetPrimitiveArrayCritical()ReleasePrimitiveArrayCritical()访问像素阵列。考虑到避免制作像素阵列的副本,这样做可能会更有效率,但是绝对不能确定您正在使用的方法会制作副本。 (特别注意,GetIntArrayElements()的第二个参数是输出变量;它报告是否已创建副本,但不指示该副本)。

关于java - JNI SetFloatArrayElement()不起作用,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/40409197/

10-10 16:01