Reputation: 588
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.
Upvotes: 1
Views: 3732
Reputation: 3973
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.
Upvotes: 4
Reputation: 20812
[java/lang/Long
should be written as [Ljava/lang/Long;
and refers to a type, not a class.
The class is Ljava/lang/Long;
, which consistent with what NewObjectArray
requires—the class for the elements:
jobjectArray NewObjectArray(JNIEnv *env, jsize length,
jclass elementClass, jobject initialElement);
BTW—Java does support primitive long
arrays, which might be faster or simplier if you can change your native method return type.
Upvotes: 1