我正在编写一个代码,它必须使用JNI将长数组从C返回到java。但是方法(* env) - > FindClass在我尝试的任何地方都返回NULL。
这是我的代码:
// Returns a 2D long array from C to Java
JNIEXPORT jobjectArray JNICALL Java_awax_tools_AcquisitionWrapper_startAcquisition (JNIEnv *env, jobject obj) {
// (...) Acquisition code
// The 2D long array to return
long** primitive2DArray = data;
// Get the long array class
jclass longArrayClass = (*env)->FindClass(env, "[java/lang/Long");
// Check if we properly got the long array class
if (longArrayClass == NULL) {
// Ooops
return NULL;
}
// Create the returnable 2D array
jobjectArray myReturnable2DArray = (*env)->NewObjectArray(env, (jsize) length1D, longArrayClass, NULL);
// Go through the firs dimension and add the second dimension arrays
for (unsigned int i = 0; i < length1D; i++) {
jlongArray longArray = (*env)->NewLongArray(env, length2D);
(*env)->SetLongArrayRegion(env, longArray, (jsize) 0, (jsize) length2D, (jlong*) primitive2DArray[i]);
(*env)->SetObjectArrayElement(env, myReturnable2DArray, (jsize) i, longArray);
(*env)->DeleteLocalRef(env, longArray);
}
// Return a Java consumable 2D long array
return myReturnable2DArray;
}
我也尝试过:
(*env)->FindClass(env, "[L")
(*env)->FindClass(env, "[Long")
(*env)->FindClass(env, "[java.lang.Long")
但它们似乎都不起作用。
答案 0 :(得分:3)
如果你真的想要一组java.lang.Long
个对象,你必须写[Ljava/lang/Long;
。如果你创建了一个数组,那么在Java端就会得到[[Ljava/lang/Long;
Long[][]
。
然而,这非常低效。您必须为该阵列中的每个数字创建一个对象。使用Long.valueOf
can give you cached objects,但我怀疑该数组中的许多值是否符合有符号字节。
您应该使用原始Long
值,而不是long
个对象。除了代码的第一行之外的所有内容都已经这样做了。原始long
数组的正确内部名称为[J
:
jclass longArrayClass = (*env)->FindClass(env, "[J");
您的其余代码是正确的,该方法将返回long[][]
。
但请注意:您没有说明您正在使用哪个平台,但在Windows上,这仍然不起作用:long
只有一个int
伪装,它也是32位值。另一方面,jlong
总是有64位,并且因为这个原因而被long long
类型定义。你是盲目地投射指针,所以你的代码会尝试复制你实际拥有的数据的两倍。
答案 1 :(得分:1)
[java/lang/Long
应写为[Ljava/lang/Long;
并引用类型,而不是类。
该课程为Ljava/lang/Long;
,与NewObjectArray
要求的内容一致 - 元素的类:
jobjectArray NewObjectArray(JNIEnv *env, jsize length,
jclass elementClass, jobject initialElement);
BTW-Java确实支持原始long
数组,如果您可以更改本机方法返回类型,则可能更快或更简单。