如何通过JNI实现Java三维数组到C++的传递与结果返回
JNI传递三维float数组问题与实现
问题描述
我目前在做项目开发,需要在C侧处理三维数组的计算逻辑:先把三维数组从Java端传到C端,计算完成后再把结果返回Java。我用JNI做两端交互,但接触JNI时间短,相关经验不足,现在正在写测试示例给后续开发做参考。
目前我已经跑通了二维数组的传递逻辑,二维数组的实现参考了现有公开方案,但三维数组的传递一直没调通。
已验证可用的二维数组传递C++代码
float** testFunction(float **a) { printf("Hello from JNI!\n"); printf("Point at %d,%d is: %f\n", 1, 2, a[1][2]); return a[1][2]; } jfloat JNICALL Java_JNIArray_integrateWithTrapezoid(JNIEnv *env, jobject thisObj, jobjectArray jarr) { int sizex = env->GetArrayLength(jarr); jfloatArray dim = (jfloatArray)env->GetObjectArrayElement(jarr, 0); int sizey = env->GetArrayLength(dim); float **localArray; localArray = new float *[sizex]; for (int i = 0; i < sizex; i++) { jfloatArray oneDim = (jfloatArray)env->GetObjectArrayElement(jarr, i); jfloat *element = env->GetFloatArrayElements(oneDim, 0); localArray[i] = new float[sizey]; for (int j = 0; j < sizey; j++) { localArray[i][j] = element[j]; } } return testFunction(localArray); }
如果有人能提供三维数组传递的实现思路我会非常感谢,目前我对这部分的实现逻辑还没理清楚,如果我漏了什么必要的信息可以随时提。
谢谢。
更新:已跑通的三维数组传递实现
在其他开发者的帮助下,我已经完成了可正常运行的三维数组传递方案,代码如下:
void trapezoidalintegral(float ***a) { printf("Hello from JNI!\n"); printf("Point at %d, %d, %d is: %f\n", 1, 2, 2, a[1][2][2]); return; } float *thirdLevel(JNIEnv *env, jfloatArray arr) { jsize len = env->GetArrayLength(arr); float *ret = new float[len]; env->GetFloatArrayRegion(arr, 0, len, ret); return ret; } float **secondLevel(JNIEnv *env, jobjectArray arr) { jsize len = env->GetArrayLength(arr); float **ret = new float *[len]; for (int i = 0; i < len; i++) { jobject item = env->GetObjectArrayElement(arr, i); ret[i] = thirdLevel(env, (jfloatArray)item); env->DeleteLocalRef(item); } return ret; } float ***firstLevel(JNIEnv *env, jobjectArray arr) { jsize len = env->GetArrayLength(arr); float ***ret = new float **[len]; for (int i = 0; i < len; i++) { jobject item = env->GetObjectArrayElement(arr, i); ret[i] = secondLevel(env, (jobjectArray)item); env->DeleteLocalRef(item); } return ret; } JNIEXPORT jobjectArray JNICALL Java_JNIArray_integrateWithTrapezoid(JNIEnv *env, jobject thisObj, jobjectArray jarr) { float ***returningArray; returningArray = firstLevel(env, jarr); trapezoidalintegral(returningArray); jclass *pClass; jclass cls1; jclass jcls1; jclass jcls2; jobject obj2; cls1 = env->GetObjectClass(thisObj); // jfieldID fid1 = env->GetFieldID(cls1, "ptr", "J"); // pClass = (jclass *)env->GetLongField(thisObj, fid1); jcls1 = env->FindClass("[[F"); jcls2 = env->FindClass("[F"); jobjectArray array1 = env->NewObjectArray(3, jcls1, NULL); for (int i = 0; i < 3; i++) { jobjectArray array2 = env->NewObjectArray(3, jcls2, NULL); for (int j = 0; j < 3; j++) { jfloatArray array3 = env->NewFloatArray(3); env->SetFloatArrayRegion(array3, 0, 3, returningArray[i][j]); env->SetObjectArrayElement(array2, j, array3); } env->SetObjectArrayElement(array1, i, array2); } env->DeleteLocalRef(cls1); env->DeleteLocalRef(jcls1); env->DeleteLocalRef(jcls2); return array1; }
这个实现把数组解析拆成了三层函数,分别处理最外层三维数组、中间二维数组、最内层一维float数组,逐层把Java的数组对象转换成C++侧的三级指针;计算完成后再反过来逐层构造Java侧的三维数组对象返回,每一层取完数组元素就及时删掉局部引用,避免JNI局部引用溢出。
内容的提问来源于stack exchange,提问作者Nic Bolton
相关产品推荐
相关产品推荐

