137 votes

Comment retourner un tableau de JNI à Java ?

J'essaie d'utiliser le NDK Android.

Existe-t-il un moyen de renvoyer un tableau (dans mon cas un int[] ) créé en JNI vers Java ? Si c'est le cas, veuillez fournir un exemple rapide de la fonction JNI qui ferait cela.

-Merci

122voto

Jherico Points 12554

Si vous avez examiné la documentation et que vous avez encore des questions, cela devrait faire partie de votre question initiale. Dans ce cas, la fonction JNI de l'exemple crée un certain nombre de tableaux. Le tableau extérieur est composé d'un tableau d'objets créé avec la fonction JNI NewObjectArray() . Du point de vue de JNI, c'est tout ce qu'un tableau à deux dimensions est, un tableau d'objets contenant un certain nombre d'autres tableaux internes.

La boucle for suivante crée les tableaux internes qui sont de type int[] en utilisant la fonction JNI NewIntArray() . Si vous souhaitez simplement renvoyer un tableau unidimensionnel d'ints, alors la fonction NewIntArray() est ce que vous utiliserez pour créer la valeur de retour. Si vous voulez créer un tableau unidimensionnel de chaînes de caractères, vous utiliserez la fonction NewObjectArray() mais avec un paramètre différent pour la classe.

Puisque vous voulez retourner un tableau d'int, votre code va ressembler à quelque chose comme ceci :

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

0 votes

Oui, je l'ai déjà fait. J'avais du mal à comprendre l'exemple lié à mon problème (le dernier), et je me demandais si quelqu'un pouvait m'expliquer un exemple plus simple en retournant simplement un int[].

0 votes

EDIT : Veuillez ignorer mon commentaire précédent, le code ci-dessus fonctionne. Merci ! C'est très utile.

3 votes

EDIT2 : Le code fonctionne, mais vous devez changer tmp dans le SetIntArrayRegion(...) pour remplir.

41voto

zajac.m2 Points 348

Si quelqu'un veut savoir comment retourner un tableau de String[] :

code java

private native String[] data();

exportation locale

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

code natif

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

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

0voto

Paramita Points 22

En fonction de la question posée, ceci est déjà expliqué dans la première réponse, à savoir comment passer int[] via jobjectArray. Mais voici un exemple de la façon dont nous pouvons retourner un jobjectArray qui contient des listes de données. Cela peut s'avérer utile dans certaines situations, par exemple lorsque quelqu'un a besoin de renvoyer des données au format 2D pour dessiner une ligne avec des points x et y. L'exemple ci-dessous montre comment un jobjectArray peut renvoyer des données dans le format suivant :

Entrée Java dans la JNI :
Tableau[ Arraylist de x points flottants][ Arraylist de points flottants y]

Sortie JNI vers java :
jobjectArray [ Arraylist de x points flottants] [ Arraylist de points flottants y]

    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;

-5voto

Jeyanth Points 13

La solution simple est d'écrire les données du tableau dans un fichier en C, puis d'accéder à ce fichier en Java.

0 votes

Excellente solution !

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X