Susi
Susi

Reputation: 11

How to return more than one array from JNI to Java?

I am using Android NDK to access a C function from Java. The C function takes in one array and returns three arrays as its arguments.

Most documentation and examples show how to return one array object using the SetIntArrayRegion() or similar methods by returning jarray via the function return value. This accounts for one array, how do I return the remaining arrays? Is there a way to return them through function arguments? I tried but without success so far.

Please provide a quick example of the JNI function that would do this or point me to an appropriate documentation. I would very much appreciate.

Thank You.

Upvotes: 1

Views: 1222

Answers (1)

Alex Cohn
Alex Cohn

Reputation: 57183

You have two options when you want to return more than one "thing" from a function (and this is not specific to JNI): either create a wrapper object that holds all the results (in your case, a Java class that has 3 array fields), or use out arguments. Probably, in your case the latter may be easier, if you know the lengths before the call.

So, in Java, you write something like

package p;

public class C {

    public void f() {

        byte[] array1 = new byte[10];
        int[] array2 = new int[20];
        String[] array3 = new String[5];

        fillArrays(array1, array2, array3);
    }
    native void fillArrays(byte[] byteArray, int[] intArray, String[] stringArray);
}

Now, in C this looks like this:

JNIEXPORT void JNICALL 
Java_p_C_fillArrays(JNIEnv *env, jobject thisC, jbyteArray byteArray, jintArray intArray, jobjectArray stringArray)
{
    jboolean isCopy;
    jint i = 0;
    char* names[] = {"one", "two", "three"};

    jbyte *c_byteArray = (*env)->GetByteArrayElements(env, byteArray, &isCopy);
    for (i=0; i<(*env)->GetArrayLength(env, byteArray); i++) {
        c_byteArray[i] = (jbyte)i;
    }
    (*env)->ReleaseByteArrayElements(env, byteArray, c_byteArray, 0);

    jint *c_intArray = (*env)->GetIntArrayElements(env, intArray, &isCopy);
    for (i=0; i<(*env)->GetArrayLength(env, intArray); i++) {
        c_intArray[i] = i;
    }
    (*env)->ReleaseIntArrayElements(env, intArray, c_intArray, 0);

    for (i=0; i<(*env)->GetArrayLength(env, stringArray) && i<sizeof(names)/sizeof(names[0]); i++) {
        (*env)->SetObjectArrayElement(env, stringArray, i, (*env)->NewStringUTF(env, names[i]));
    }
}

Upvotes: 1

Related Questions