Возврат 2D примитивного массива из C в Java из JNI / NDK - PullRequest
9 голосов
/ 26 мая 2011

Я нашел большое количество документации о том, как сгенерировать двумерный примитивный массив в JNI и вернуть его в Java. Но эти фрагменты информации не описывают, как передать уже существующий 2D массив с плавающей точкой (float **), заданный контекст в C .

Чтобы описать мою проблему явно, я добавлю C псевдокод того, что я хотел бы реализовать:

// Returns a 2D float array from C to Java
jfloatArray ndk_test_getMy2DArray(JNIEnv* env, jobject thiz, jlong context)
{
    // Cast my context reference
    MyContextRef contextRef = (MyContextRef) context;

    // In case we need it below
    unsigned int length = MyContextGet1DLength(contextRef);

    // Get the 2D Array we want to "Cast"
    float** primitive2DArray = MyContextGet2DArray(contextRef);

    // Hokus pokus...
    // We do something to create the returnable data to Java
    //
    // Below is the missing piece that would convert the primitive
    // 2D array into something that can be returned consumed and consumed
    // by Java

    jfloatArray myReturnable2DArray

    return myReturnable2DArray;
}

Я предполагаю, что это не так просто, учитывая, что я не смог найти ничего, описывающего этот сценарий.

Спасибо за любую полезную информацию.

Ответы [ 3 ]

17 голосов
/ 27 мая 2011

Спасибо Тимо за вашу помощь и ссылку.Для потомков я добавляю полный набор кодов, который будет проходить через процесс создания двумерного примитивного массива, потребляемого Java, из существующего двумерного примитивного массива C.

// Returns a 2D float array from C to Java
jobjectArray ndk_test_getMy2DArray(JNIEnv* env, jobject thiz, jlong context)
{
    // Cast my context reference
    MyContextRef contextRef = (MyContextRef) context;

    // Get the length for the first and second dimensions
    unsigned int length1D = MyContextGet1DLength(contextRef);
    unsigned int length2D = MyContextGet2DLength(contextRef);

    // Get the 2D float array we want to "Cast"
    float** primitive2DArray = MyContextGet2DArray(contextRef);

    // Get the float array class
    jclass floatArrayClass = (*env)->FindClass(env, "[F");

    // Check if we properly got the float array class
    if (floatArrayClass == NULL)
    {
        // Ooops
        return NULL;
    }

    // Create the returnable 2D array
    jobjectArray myReturnable2DArray = (*env)->NewObjectArray(env, (jsize) length1D, floatArrayClass, NULL);

    // Go through the firs dimension and add the second dimension arrays
    for (unsigned int i = 0; i < length1D; i++)
    {
        jfloatArray floatArray = (*env)->NewFloatArray(env, length2D);
        (*env)->SetFloatArrayRegion(env, floatArray, (jsize) 0, (jsize) length2D, (jfloat*) primitive2DArray[i]);
        (*env)->SetObjectArrayElement(env, myReturnable2DArray, (jsize) i, floatArray);
        (*env)->DeleteLocalRef(env, floatArray);
    }

    // Return a Java consumable 2D float array
    return myReturnable2DArray;
}
2 голосов
/ 26 мая 2011

К сожалению, я не думаю, что вы можете передать поплавки C до Java, вам придется превратить массив в двумерный массив jfloat, преобразовав каждый член в jFloat.

Вам нужно будет создать многомерный массив jFloatArray, затем выполнить итерацию собственного массива C, преобразовать каждый элемент в его представление jFloat и сохранить его в той же позиции в только что созданном jFloatArray.документация должна объяснить это немного глубже.

0 голосов
/ 28 июля 2016

Я сделал простую функцию для преобразования:

jobjectArray getJNIArray(JNIEnv *env, jobject obj, const vector<vector<float> >& arr) {
    jclass floatClass = env->FindClass("[F"); //
    jsize height = arr.size();

    // Create the returnable 2D array
    jobjectArray jObjarray = env->NewObjectArray(height, floatClass, NULL);

    // Go through the first dimension and add the second dimension arrays
    for (unsigned int i = 0; i < height; i++) {
        jfloatArray floatArray = env->NewFloatArray(arr[i].size());
        env->SetFloatArrayRegion(floatArray, (jsize) 0, (jsize) arr[i].size(), (jfloat*) arr[i].data());
        env->SetObjectArrayElement(jObjarray, (jsize) i, floatArray);
        env->DeleteLocalRef(floatArray);
    }

    return jObjarray;
}
...