Как вернуть массив из JNI в Java? - PullRequest
114 голосов
/ 23 октября 2009

Я пытаюсь использовать Android NDK.

Есть ли способ вернуть массив (в моем случае int[]), созданный в JNI, в Java? Если да, приведите краткий пример функции JNI, которая могла бы сделать это.

-Спасибо

Ответы [ 4 ]

107 голосов
/ 23 октября 2009

Если вы изучили документацию и у вас остались вопросы, которые должны быть частью вашего первоначального вопроса. В этом случае функция JNI в этом примере создает несколько массивов. Внешний массив состоит из массива 'Object', создаваемого с помощью функции JNI NewObjectArray(). С точки зрения JNI, это все двухмерный массив, массив объектов, содержащий ряд других внутренних массивов.

Следующий цикл for создает внутренние массивы типа int [] с использованием функции JNI NewIntArray(). Если вы просто хотите вернуть одномерный массив целых чисел, то для создания возвращаемого значения вы должны использовать функцию NewIntArray(). Если вы хотите создать одномерный массив строк, вы должны использовать функцию NewObjectArray(), но с другим параметром для класса.

Так как вы хотите вернуть массив int, ваш код будет выглядеть примерно так:

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;
}
34 голосов
/ 10 мая 2013

, если кто-то хочет знать, как вернуть массив String []:

код Java

private native String[] data();

собственный экспорт

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

нативный код

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

по ссылке: http://www.coderanch.com/t/326467/java/java/Returning-String-array-program-Java

0 голосов
/ 23 января 2019

Исходя из заданного вопроса, это уже объяснялось в первом ответе: как мы можем передать int [] через jobjectArray. Но вот пример того, как мы можем вернуть jobjectArray, который содержит списки данных. Это может быть полезно, например, для ситуаций, когда кому-то нужно вернуть данные в формате 2D, чтобы нарисовать линию с точками x и y. В приведенном ниже примере показано, как jobjectArray может возвращать данные в форме следующего формата:

Ввод Java в JNI:
Массив [Arraylist x точек с плавающей точкой] [Arraylist y точек с плавающей точкой]

вывод JNI в java:
jobjectArray [Arraylist из x точек с плавающей точкой] [Arraylist из 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;
0 голосов
/ 03 июля 2018

Простое решение заключается в том, что записать данные массива в файл из C, а затем получить доступ к файлу из Java

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...