Bagaimana cara mengembalikan array dari JNI ke Java?

130

Saya mencoba menggunakan NDK android.

Apakah ada cara untuk mengembalikan array (dalam kasus saya dan int[]) yang dibuat di JNI ke Java? Jika demikian, berikan contoh cepat fungsi JNI yang akan melakukan ini.

-Terima kasih

RyanCheu
sumber

Jawaban:

120

Jika Anda telah memeriksa dokumentasi dan masih memiliki pertanyaan yang harus menjadi bagian dari pertanyaan awal Anda. Dalam hal ini, fungsi JNI dalam contoh membuat sejumlah array. Array luar terdiri dari larik 'Objek' yang dibuat dengan fungsi JNI NewObjectArray(). Dari perspektif JNI, itu semua array dua dimensi adalah, array objek yang berisi sejumlah array batin lainnya.

Berikut ini untuk loop membuat array dalam yang bertipe int [] menggunakan fungsi JNI NewIntArray(). Jika Anda hanya ingin mengembalikan array int satu dimensi, maka NewIntArray()fungsinya adalah apa yang Anda gunakan untuk membuat nilai balik. Jika Anda ingin membuat array dimensi tunggal dari Strings maka Anda akan menggunakan NewObjectArray()fungsi tetapi dengan parameter yang berbeda untuk kelas.

Karena Anda ingin mengembalikan array int, maka kode Anda akan terlihat seperti ini:

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
sumber
Ya, saya sudah melakukannya. Saya mengalami kesulitan memahami contoh yang terkait dengan masalah saya (yang terakhir), dan saya bertanya-tanya apakah ada orang yang mau menjelaskan contoh yang lebih sederhana dengan hanya mengembalikan int [].
RyanCheu
EDIT: Harap abaikan komentar saya sebelumnya, kode di atas tidak berfungsi. Terima kasih! Itu sangat membantu.
RyanCheu
3
EDIT2: Kode berfungsi, tetapi Anda harus mengubah tmp di SetIntArrayRegion (...) untuk diisi.
RyanCheu
41

jika seseorang ingin tahu cara mengembalikan array String []:

kode java

private native String[] data();

ekspor asli

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

kode asli

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

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

zajac.m2
sumber
0

Berdasarkan pertanyaan yang diajukan, ini sudah dijelaskan dalam jawaban pertama bahwa bagaimana kita dapat meneruskan int [] melalui jobjectArray. Tapi di sini adalah contoh bagaimana kita bisa mengembalikan jobjectArray yang berisi daftar data. Ini dapat membantu untuk situasi misalnya: ketika seseorang perlu mengembalikan data dalam format 2D untuk menggambar beberapa garis dengan poin x dan y. Contoh di bawah ini menunjukkan bagaimana sebuah jobjectArray dapat mengembalikan data dalam bentuk format berikut:

Input Java ke JNI:
Array [ Arraylistdari x float points] [ Arraylistof y float points]

Output JNI ke java:
jobjectArray[ Arraylistof x float points] [ Arraylistof y float points]

    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
sumber
-6

Solusi sederhana adalah menulis data array dalam file dari C, dan kemudian mengakses file dari Java

Jeyanth
sumber