Возвращение класса C ++ в Java через JNI - PullRequest
14 голосов
/ 11 ноября 2009

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

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

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

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, когда я делаю фактический вызов. Что не так?

Ответы [ 3 ]

11 голосов
/ 25 декабря 2009

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

Сначала я бы создал подобный объект в Java. Затем из C ++ я бы его создал и передал все значения.

(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 будет иметь конструктор, который принимает строку. Я считаю, что решение простое и эффективное.

5 голосов
/ 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 (ну, я добавил кое-что подсчитывающее, но это довольно продвинутое) Надеюсь, это поможет.

Art

4 голосов
/ 11 ноября 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?

...