我尝试修改jfloatArray中的某些值,然后再将其返回到java Android代码。
我发现我无法使用常规方式newArray[i] = result[i];
来执行此操作,而应该env->SetFloatArrayElement(newArray,i,result[i]);
。
问题是此函数抛出错误:
[armeabi-v7a]编译++ arm:tensorflow_mnist< = tensorflow_jni.cc 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,导致[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;
}
答案 0 :(得分:2)
我尝试修改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()
的第二个参数是输出变量;它报告是否已复制,但不指示复制。