How to return an array from JNI to Java?

99,227

Solution 1

If you've examined the documentation and still have questions that should be part of your initial question. In this case, the JNI function in the example creates a number of arrays. The outer array is comprised of an 'Object' array creating with the JNI function NewObjectArray(). From the perspective of JNI, that's all a two dimensional array is, an object array containing a number of other inner arrays.

The following for loop creates the inner arrays which are of type int[] using the JNI function NewIntArray(). If you just wanted to return a single dimensional array of ints, then the NewIntArray() function is what you'd use to create the return value. If you wanted to create a single dimensional array of Strings then you'd use the NewObjectArray() function but with a different parameter for the class.

Since you want to return an int array, then your code is going to look something like this:

JNIEXPORT jintArray JNICALL Java_ArrayTest_initIntArray(JNIEnv *env, jclass cls, int size)
{
 jintArray result;
 result = (*env)->NewIntArray(env, size);
 if (result == NULL) {
     return NULL; /* out of memory error thrown */
 }
 int i;
 // fill a temp structure to use to populate the java int array
 jint fill[size];
 for (i = 0; i < size; i++) {
     fill[i] = 0; // put whatever logic you want to populate the values here.
 }
 // move from the temp structure to the java structure
 (*env)->SetIntArrayRegion(env, result, 0, size, fill);
 return result;
}

Solution 2

if someone would like to know how to return String[] array:

java code

private native String[] data();

native export

JNIEXPORT jobjectArray JNICALL Java_example_data() (JNIEnv *, jobject);

native code

  JNIEXPORT jobjectArray JNICALL   
               Java_example_data  
  (JNIEnv *env, jobject jobj){  

    jobjectArray ret;  
    int i;  

    char *message[5]= {"first",   
                       "second",   
                       "third",   
                       "fourth",   
                       "fifth"};  

    ret= (jobjectArray)env->NewObjectArray(5,  
         env->FindClass("java/lang/String"),  
         env->NewStringUTF(""));  

    for(i=0;i<5;i++) {  
        env->SetObjectArrayElement(  
        ret,i,env->NewStringUTF(message[i]));  
    }  
    return(ret);  
  }  

from link: http://www.coderanch.com/t/326467/java/java/Returning-String-array-program-Java

Share:
99,227
RyanCheu
Author by

RyanCheu

Platform Engineer @ Quora, focusing on Android.

Updated on January 24, 2020

Comments

  • RyanCheu
    RyanCheu over 4 years

    I am attempting to use the android NDK.

    Is there a way to return an array (in my case an int[]) created in JNI to Java? If so, please provide a quick example of the JNI function that would do this.

    -Thanks

  • RyanCheu
    RyanCheu over 14 years
    Yeah, I did that already. I was having trouble understanding the example that was related to my problem ( the last one ), and I was wondering if someone would mind explaining a simpler example with just returning an int[].
  • RyanCheu
    RyanCheu over 14 years
    EDIT: Please ignore my previous comment, the above code does work. Thank you! That was very helpful.
  • RyanCheu
    RyanCheu over 14 years
    EDIT2: The code works, but you have to change tmp in the SetIntArrayRegion(...) to fill.
  • Tobi Akinyemi
    Tobi Akinyemi about 3 years
    Don't you get a NPE when you go out of scope - as fill is destructed. or does SetIntArrayRegion immediately copy the data?
  • Tobi Akinyemi
    Tobi Akinyemi about 3 years
    Great solution!
  • Jherico
    Jherico about 3 years
    Per the JNI documentation, the SetIntArrayRegion and all the similar primitive array population functions copy data into the JNI managed structure. The fill array only needs to be valid for the duration of the function.
  • Umair
    Umair almost 3 years
    @Jherico, can you guide about the size variable. I mean the line "result = (*env)->NewIntArray(env, size);", and if we don't know how much size C array will throw back. Can we somehow get the size of incoming array.
  • Jherico
    Jherico about 2 years
    @Umair In C an array is just a pointer. Any function that takes a pointer to an array of values must also be passed a size value as a separate parameter. There are numerous examples in the standard C library, such as memset.
  • Farrukh Nabiyev
    Farrukh Nabiyev about 2 years
    Thanks. I could not understand what is a buffer* in the SetIntArrayRegion method call. Now I see that it is an array.
  • Wade Wang
    Wade Wang almost 2 years
    Currently in 2022, we should use env-> instead of (*env)->.