11

I have found large amounts of documentation on how to generate a 2D primitive array in JNI and returning it to Java. But these pieces of information fail to describe how to pass an already existing 2D float array (float**) given a context in C.

To describe my issue explicitly, I'll add some C pseudo code of what I would like to implement:

// Returns a 2D float array from C to Java jfloatArray ndk_test_getMy2DArray(JNIEnv* env, jobject thiz, jlong context) { // Cast my context reference MyContextRef contextRef = (MyContextRef) context; // In case we need it below unsigned int length = MyContextGet1DLength(contextRef); // Get the 2D Array we want to "Cast" float** primitive2DArray = MyContextGet2DArray(contextRef); // Hokus pokus... // We do something to create the returnable data to Java // // Below is the missing piece that would convert the primitive // 2D array into something that can be returned consumed and consumed // by Java jfloatArray myReturnable2DArray return myReturnable2DArray; } 

I'm assuming this is not straight forward, given I haven't been able to find anything describing this scenario.

Thanks for any helpful information.

3 Answers 3

20

Thanks Timo for your help and link. For posterity, I'm adding a complete code set that would go through the process of generating a 2D primitive array consumable by Java, from an existing C 2D primitive array.

// Returns a 2D float array from C to Java jobjectArray ndk_test_getMy2DArray(JNIEnv* env, jobject thiz, jlong context) { // Cast my context reference MyContextRef contextRef = (MyContextRef) context; // Get the length for the first and second dimensions unsigned int length1D = MyContextGet1DLength(contextRef); unsigned int length2D = MyContextGet2DLength(contextRef); // Get the 2D float array we want to "Cast" float** primitive2DArray = MyContextGet2DArray(contextRef); // Get the float array class jclass floatArrayClass = (*env)->FindClass(env, "[F"); // Check if we properly got the float array class if (floatArrayClass == NULL) { // Ooops return NULL; } // Create the returnable 2D array jobjectArray myReturnable2DArray = (*env)->NewObjectArray(env, (jsize) length1D, floatArrayClass, NULL); // Go through the firs dimension and add the second dimension arrays for (unsigned int i = 0; i < length1D; i++) { jfloatArray floatArray = (*env)->NewFloatArray(env, length2D); (*env)->SetFloatArrayRegion(env, floatArray, (jsize) 0, (jsize) length2D, (jfloat*) primitive2DArray[i]); (*env)->SetObjectArrayElement(env, myReturnable2DArray, (jsize) i, floatArray); (*env)->DeleteLocalRef(env, floatArray); } // Return a Java consumable 2D float array return myReturnable2DArray; } 
Sign up to request clarification or add additional context in comments.

Comments

3

I've made a simple function for conversion:

jobjectArray getJNIArray(JNIEnv *env, jobject obj, const vector<vector<float> >& arr) { jclass floatClass = env->FindClass("[F"); // jsize height = arr.size(); // Create the returnable 2D array jobjectArray jObjarray = env->NewObjectArray(height, floatClass, NULL); // Go through the first dimension and add the second dimension arrays for (unsigned int i = 0; i < height; i++) { jfloatArray floatArray = env->NewFloatArray(arr[i].size()); env->SetFloatArrayRegion(floatArray, (jsize) 0, (jsize) arr[i].size(), (jfloat*) arr[i].data()); env->SetObjectArrayElement(jObjarray, (jsize) i, floatArray); env->DeleteLocalRef(floatArray); } return jObjarray; } 

Comments

2

Unfortunately I don't think you can pass C floats up to Java, you'll have to turn the array into a 2D array of jfloats by converting every member into a jFloat.

Essentially, you'll have to create the multidimensional jFloatArray, then iterate through the native C array, convert every element into its jFloat representation and store it into the same position in the jFloatArray you just created.

This part of the documentation should explain it in a bit more depth.

3 Comments

Yes, I'm aware of this limitation. I'm sorry if it wasn't clear in my question, but what I'm asking is about that process. How can I convert that primitive 2D array into something that can be consumed by Java.
@Claudia, I've just added a link to an example in the JNI documentation.
I've added a full code set that goes through the process. Thanks for your help.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.