Возврат класса C++ в Java через JNI

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

До сих пор я ничего не возвращал, int или boolean в Java через интерфейс JNI. На этот раз я должен отправить объект через интерфейс. Я сделал аналогичное определение класса доступным как в C++, так и в Java. Я хотел бы знать, как мне создать объект, чтобы использовать его в Java.

В С++ у меня есть:

JNIEXPORT MyObject JNICALL Java_ca_X_Y_Z_C_1getMyObject(JNIEnv* env, jclass, jint number);

Эта функция будет вызываться Java для получения объекта со стороны C++ (объект содержится в синглтоне, легко доступном).

На стороне Java я просто вызываю этот метод,

MyObject anObject = C_getMyObject(3);

который должен вернуть мне вновь созданный объект.

Java в настоящее время возвращает мне UnsatisfiedLinkError, когда я делаю фактический вызов. Что случилось?


person tomzx    schedule 10.11.2009    source источник


Ответы (3)


Вот решение, которое я решил использовать:

Во-первых, я бы создал аналогичный объект на Java. Затем из С++ я бы создал его экземпляр и передал ему все значения.

(C++)
clazz = env->FindClass("java/lang/Integer");
jmethodID method = env->GetMethodID(clazz, "<init>", "(I)V");
return env->NewObject(clazz, method, (jint)anInteger);

Но потом я понял, что это не очень портативно и слишком сложно.

Вместо этого я решил вернуть строку, которую Java будет анализировать и использовать для инициализации объекта на своей стороне.

(JAVA)
String aString = "valuesoftheobject";
MyObject myObject(aString);

MyObject будет иметь конструктор, который принимает строку. Я считаю, что решение простое и эффективное.

person tomzx    schedule 25.12.2009

Еще один инструмент, на который стоит обратить внимание, — это SWIG. SWIG — отличный инструмент для создания оболочек на других языках (таких как Java, Python или C#) для существующих объектов C/C++. Он будет генерировать автоматические Java-оболочки вокруг объектов C/C++ и выполнять всю тяжелую работу JNI за вас.

Я широко использую его в Xuggler. Чтобы увидеть пример, если вы загружаете исходный код Xuggler, здесь есть объект C++:

csrc/com/xuggle/xuggler/IStreamCoder.h

Здесь я определяю файл интерфейса SWIG:

csrc/com/xuggle/xuggler/IStreamCoder.i

И при запуске через Swig он генерирует объект Java (который хранится здесь)

generate/java/com/xuggle/xuggler/IStreamCoder.java

Затем мы можем легко получить доступ к этому объекту из Java (ну, я добавлю некоторые вещи для подсчета ссылок, но это довольно сложно). Надеюсь, это поможет.

Искусство

person Art Clarke    schedule 11.12.2009

Если ваш класс MyObject определен на C++, вы не сможете получить доступ к его методам в Java. Я бы попытался определить класс-оболочку Java вокруг вашего объекта C:

Java:
public C_Object() {
   handle = createHandle();
}

private native long createHandle(); // or whatever pointer/handle type?

public void doStuff() {
   _doStuff(handle);
}

private native void _doStuff(long handle);

Если вместо этого вы можете экстраполировать C API, вы можете попробовать JNA.

Ваш UnsatisfiedLinkError может быть дополнительным символом в имени вашей функции, как написано выше, или, возможно, он не может обрабатывать возвращаемое значение MyObject?

person Community    schedule 10.11.2009