Wie kann man ein Array von JNI nach Java zurückgeben?

130

Ich versuche, das Android NDK zu verwenden.

Gibt es eine Möglichkeit, ein int[]in JNI erstelltes Array (in meinem Fall ein ) an Java zurückzugeben? Wenn ja, geben Sie bitte ein kurzes Beispiel für die JNI-Funktion, die dies tun würde.

-Vielen Dank

RyanCheu
quelle

Antworten:

120

Wenn Sie die Dokumentation geprüft haben und noch Fragen haben, die Teil Ihrer ursprünglichen Frage sein sollten. In diesem Fall erstellt die JNI-Funktion im Beispiel eine Reihe von Arrays. Das äußere Array besteht aus einem 'Object'-Array, das mit der JNI-Funktion erstellt wird NewObjectArray(). Aus der Sicht von JNI ist das alles, was ein zweidimensionales Array ist, ein Objektarray, das eine Reihe anderer innerer Arrays enthält.

Die folgende for-Schleife erstellt mithilfe der JNI-Funktion die inneren Arrays vom Typ int [] NewIntArray(). Wenn Sie nur ein eindimensionales Array von Ints zurückgeben möchten, verwenden Sie die NewIntArray()Funktion, um den Rückgabewert zu erstellen. Wenn Sie ein eindimensionales Array von Strings erstellen möchten, verwenden Sie die NewObjectArray()Funktion, jedoch mit einem anderen Parameter für die Klasse.

Da Sie ein int-Array zurückgeben möchten, sieht Ihr Code ungefähr so ​​aus:

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;
}
Jherico
quelle
Ja, das habe ich schon gemacht. Ich hatte Probleme, das Beispiel zu verstehen, das mit meinem Problem zusammenhängt (das letzte), und ich fragte mich, ob es jemandem etwas ausmachen würde, ein einfacheres Beispiel zu erklären, indem er nur ein int [] zurückgibt.
RyanCheu
EDIT: Bitte ignorieren Sie meinen vorherigen Kommentar, der obige Code funktioniert. Danke dir! Das war sehr hilfreich.
RyanCheu
3
EDIT2: Der Code funktioniert, aber Sie müssen tmp in der SetIntArrayRegion (...) ändern, um ihn zu füllen.
RyanCheu
41

Wenn jemand wissen möchte, wie er das Array String [] zurückgibt:

Java-Code

private native String[] data();

nativer Export

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

nativen 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);  
  }  

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

zajac.m2
quelle
0

Basierend auf der gestellten Frage wird dies bereits in der ersten Antwort erklärt, wie wir int [] über jobjectArray übergeben können. Hier ist ein Beispiel, wie wir ein jobjectArray zurückgeben können, das Datenlisten enthält. Dies kann beispielsweise in Situationen hilfreich sein, in denen jemand Daten im 2D-Format zurückgeben muss, um eine Linie mit x- und y-Punkten zu zeichnen. Das folgende Beispiel zeigt, wie ein jobjectArray Daten in folgendem Format zurückgeben kann:

Java-Eingabe in das JNI:
Array [ Arraylistvon x Gleitkommazahlen] [ Arraylistvon y Gleitkommazahlen]

JNI-Ausgabe an Java:
jobjectArray[ Arraylistvon x Gleitkomma] [ Arraylistvon y Gleitkomma]

    extern "C" JNIEXPORT jobjectArray JNICALL
        _MainActivity_callOpenCVFn(
                JNIEnv *env, jobject /* this */,
                jobjectArray list) {

         //Finding arrayList class and float class(2 lists , one x and another is y)
            static jclass arrayListCls = static_cast<jclass>(env->NewGlobalRef(env->FindClass("java/util/ArrayList")));
            jclass floatCls = env->FindClass("java/lang/Float");
         //env initialization of list object and float
            static jmethodID listConstructor = env->GetMethodID(arrayListCls, "<init>", "(I)V");
            jmethodID alGetId  = env->GetMethodID(arrayListCls, "get", "(I)Ljava/lang/Object;");
            jmethodID alSizeId = env->GetMethodID(arrayListCls, "size", "()I");
            static jmethodID addElementToList = env->GetMethodID(arrayListCls, "add", "(Ljava/lang/Object;)Z");

            jmethodID floatConstructor = env->GetMethodID( floatCls, "<init>", "(F)V");
            jmethodID floatId = env->GetMethodID(floatCls,"floatValue", "()F");


        //null check(if null then return)
        if (arrayListCls == nullptr || floatCls == nullptr) {
            return 0;
        }

    //     Get the value of each Float list object in the array
        jsize length = env->GetArrayLength(list);

        //If empty
        if (length < 1) {
            env->DeleteLocalRef(arrayListCls);
            env->DeleteLocalRef(floatCls);
            return 0;
        }

// Creating an output jObjectArray
    jobjectArray outJNIArray = env->NewObjectArray(length, arrayListCls, 0);

        //taking list of X and Y points object at the time of return
        jobject  xPoint,yPoint,xReturnObject,yReturnObject;

            //getting the xList,yList object from the array
            jobject xObjFloatList = env->GetObjectArrayElement(list, 0);
            jobject yObjFloatList = env->GetObjectArrayElement(list, 1);


     // number of elements present in the array object
        int xPointCounts = static_cast<int>(env->CallIntMethod(xObjFloatList, alSizeId));

        static jfloat xReturn, yReturn;
                jobject xReturnArrayList = env->NewObject(arrayListCls,listConstructor,0);
        jobject yReturnArrayList = env->NewObject(arrayListCls,listConstructor,0);

    for (int j = 0; j < xPointCounts; j++) {
            //Getting the x points from the x object list in the array
            xPoint = env->CallObjectMethod(xObjFloatList, alGetId, j);
            //Getting the y points from the y object list in the array
            yPoint = env->CallObjectMethod(yObjFloatList, alGetId, j);

//Returning jobjectArray(Here I am returning the same x and points I am receiving from java side, just to show how to make the returning `jobjectArray`)  

            //float x and y values
            xReturn =static_cast<jfloat >(env->CallFloatMethod(xPoint, floatId,j));
            yReturn =static_cast<jfloat >(env->CallFloatMethod(yPoint, floatId,j));


            xReturnObject = env->NewObject(floatCls,floatConstructor,xReturn);
             yReturnObject = env->NewObject(floatCls,floatConstructor,yReturn);

            env->CallBooleanMethod(xReturnArrayList,addElementToList,xReturnObject);


            env->CallBooleanMethod(yReturnArrayList,addElementToList,yReturnObject);
            env->SetObjectArrayElement(outJNIArray,0,xReturnArrayList);
            env->SetObjectArrayElement(outJNIArray,1,yReturnArrayList);
        __android_log_print(ANDROID_LOG_ERROR, "List of X and Y are saved in the array","%d", 3);

    }

    return outJNIArray;
Paramita
quelle
-6

Eine einfache Lösung besteht darin, die Array-Daten von C in eine Datei zu schreiben und dann von Java aus auf die Datei zuzugreifen

Jeyanth
quelle