Передача float[] из C в Java с использованием JNI

#java #c #java-native-interface

#java #c #java-native-interface

Вопрос:

Я пытаюсь «передать» (т. Е. Скопировать) необработанный массив с плавающей запятой из C в Java. Структура C , содержащая исходный массив:

 struct foo_cpp {
    float a[16];
};
 

Класс Java, содержащий целевой массив:

 public class foo_java {
    public float a[];

    public foo_java() {
        a = new float[16];
    }
}
 

Функция C пытается передать данные в класс Java:

 extern "C" JNIEXPORT jobject JNICALL Java_com_example_myapp_Controller_process_1frame(JNIEnv *env, jclass clazz)
{
    // C   "source array"
    foo_cpp fc;
    // Initialize fc.a here...

    // Convert from cpp to java
    jobject foo_object;
    {
        // Create the foo object
        jclass foo_class_id = env->FindClass("com/example/myapp/foo_java");
        jmethodID foo_ctor_id = env->GetMethodID(foo_class_id, "<init>", "()V");
        foo_object = env->NewObject(foo_class_id, foo_ctor_id);

        // Get the field ID
        jfieldID field_id = env->GetFieldID(foo_class_id, "a", "[F");

        // Set the fields
        {
            // Get pointer to Java object float array (Get pointer to Java class foo_java::a)
            jobject field_data = env->GetObjectField(foo_object, field_id);
            jfloatArray *fa = reinterpret_cast<jfloatArray*>(amp;field_data);
            float *fa_raw = env->GetFloatArrayElements(*fa, nullptr);
            for (int i = 0; i < 16; i  )
                fa_raw[i] = static_cast<float>(fc.a[i]);
        }
    }
    
    return foo_object;
}
 

Однако при запуске этого значения в объекте Java не соответствуют ожидаемым.

Что я упускаю / делаю неправильно?

Комментарии:

1. Вы пропускаете вызов ReleaseFloatArrayElements . Вам нужно вызвать его после того, как вы закончите использовать fa_raw , с 0 в качестве mode параметра.

2. jnicookbook.owsiak.org/recipe-No-011

Ответ №1:

Код, упомянутый в вопросе, оказался работающим, как и ожидалось. Значения float были правильными, и это был классический случай неправильной интерпретации / многоуровневых проблем.

Однако, как указал @Michael в комментарии: вызов ReleaseFloatArrayElements() необходим для предотвращения утечки памяти.

Я создал сообщение в блоге по этому поводу: https://blog.insane.engineer/post/cpp_length_prefixed_strings /