#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
параметра.
Ответ №1:
Код, упомянутый в вопросе, оказался работающим, как и ожидалось. Значения float были правильными, и это был классический случай неправильной интерпретации / многоуровневых проблем.
Однако, как указал @Michael в комментарии: вызов ReleaseFloatArrayElements()
необходим для предотвращения утечки памяти.
Я создал сообщение в блоге по этому поводу: https://blog.insane.engineer/post/cpp_length_prefixed_strings /