我正在尝试将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()
。还要注意,使用这种方法,如果要提交更改(如您所做的那样),则必须使用模式0
或JNI_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/