JNI'den Java'ya bir dizi nasıl döndürülür?


130

Android NDK'yı kullanmaya çalışıyorum.

int[]JNI'de oluşturulmuş bir diziyi (benim durumumda bir ) Java'ya döndürmenin bir yolu var mı ? Öyleyse, lütfen bunu yapacak JNI işlevinin hızlı bir örneğini sağlayın.

-Teşekkürler

Yanıtlar:


120

Belgeleri incelediyseniz ve hala ilk sorunuzun parçası olması gereken sorularınız varsa. Bu durumda, örnekteki JNI işlevi bir dizi dizi oluşturur. Dış dizi, JNI işlevi ile oluşturulan bir 'Nesne' dizisinden oluşur NewObjectArray(). JNI perspektifinden bakıldığında, bu iki boyutlu bir dizi, bir dizi başka iç diziyi içeren bir nesne dizisidir.

Aşağıdaki for döngüsü, JNI işlevini kullanarak int [] türündeki iç dizileri oluşturur NewIntArray(). Yalnızca tek boyutlu bir tamsayı dizisi döndürmek istiyorsanız, NewIntArray()işlev, dönüş değerini oluşturmak için kullanacağınız şeydir. Tek boyutlu bir Dizeler dizisi oluşturmak istiyorsanız, bu NewObjectArray()işlevi sınıf için farklı bir parametre ile kullanırsınız .

Bir int dizisi döndürmek istediğinize göre, kodunuz şuna benzer:

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

Evet, bunu zaten yaptım. Sorunumla ilgili olan örneği (sonuncusu) anlamakta güçlük çekiyordum ve birinin daha basit bir örneği sadece bir int [] döndürerek açıklamanın sakıncası olup olmayacağını merak ediyordum.
RyanCheu

DÜZENLEME: Lütfen önceki yorumumu dikkate almayın, yukarıdaki kod çalışıyor. Teşekkür ederim! Bu çok yardımcı oldu.
RyanCheu

3
DÜZENLEME2: Kod çalışır, ancak doldurmak için SetIntArrayRegion (...) içindeki tmp'yi değiştirmeniz gerekir.
RyanCheu

41

String [] dizisinin nasıl döndürüleceğini bilmek isterse:

java kodu

private native String[] data();

yerel ihracat

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

yerel kod

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

bağlantıdan: http://www.coderanch.com/t/326467/java/java/Returning-String-array-program-Java


0

Sorulan soruya dayanarak, bu, int [] 'i jobjectArray aracılığıyla nasıl geçirebiliriz şeklindeki ilk cevapta zaten açıklanmıştır. Ama işte veri listelerini içeren bir jobjectArray'i nasıl döndürebileceğimizin bir örneği. Bu, örneğin şu durumlar için yararlı olabilir: birinin x ve y noktaları olan bir çizgi çizmek için 2B formatında veri döndürmesi gerektiğinde. Aşağıdaki örnek, bir jobjectArray öğesinin aşağıdaki formatta nasıl veri döndürebileceğini gösterir:

JNI'ye Java girdisi:
Dizi [ Arraylistx kayan nokta] [ Arraylisty kayan nokta]

JNI çıktısı java'ya:
jobjectArray[ Arraylistx kayan nokta] [ Arraylisty kayan nokta]

    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;

-6

Basit çözüm, dizi verilerini C'den bir dosyaya yazmak ve ardından dosyaya Java'dan erişmektir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.