如何使用JNI返回2D长数组 [英] How to return 2D long array with JNI
问题描述
我正在编写一个代码,必须使用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")
但是它们似乎都不起作用.
如果您确实想要java.lang.Long
对象的数组,则必须编写[Ljava/lang/Long;
.如果创建一个数组,则会得到[[Ljava/lang/Long;
,在Java端为Long[][]
.
但是,这效率很低.您必须在该数组内为每个数字创建一个对象.使用Long.valueOf
可以为您提供缓存的对象,但我怀疑该数组中的许多值是否适合带符号的字节.>
您应该使用原始的long
值而不是Long
对象.除了代码第一行之外的所有内容都已在执行此操作.原始long
s数组的正确内部名称是[J
:
jclass longArrayClass = (*env)->FindClass(env, "[J");
其余代码正确无误,该方法将返回long[][]
.
但是要当心:您没有在说要使用哪个平台,但是例如在Windows上,这仍然行不通:long
只是变相的int
,它也是32位值.另一方面,jlong
始终具有64位,并且正是由于这个原因而被类型定义为long long
.您会盲目地投射指针,因此您的代码将尝试复制实际上两倍的数据.
I'm writing a code which must return a long array from C to java using JNI. But the method (*env)->FindClass returns NULL whatever I tried.
Here is my code :
// 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;
}
I also tried with :
(*env)->FindClass(env, "[L")
(*env)->FindClass(env, "[Long")
(*env)->FindClass(env, "[java.lang.Long")
But none of them seems to work.
If you really want an array of java.lang.Long
objects, you have to write [Ljava/lang/Long;
. If you create an array of those, you get [[Ljava/lang/Long;
which would be Long[][]
on the Java side.
However, this is terribly inefficient. You have to create an object for every single number inside that array. Using Long.valueOf
can give you cached objects but I doubt that many values inside that array fit into a signed byte.
Instead of Long
objects, you should use primitive long
values. Everything except the first line of your code is already doing that. The correct internal name for an array of primitive long
s is [J
:
jclass longArrayClass = (*env)->FindClass(env, "[J");
The rest of your code is correct and the method will return a long[][]
.
But watch out: You aren't saying anything about which platform you're using, but on Windows for example, this still won't work: A long
there is just an int
in disguise, it's also a 32 bit value. A jlong
on the other hand always has 64 bits and is typedef'd to a long long
for exactly that reason. You're blindly casting the pointers, so your code would try to copy twice as much data as you actually have.
这篇关于如何使用JNI返回2D长数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!