2009-11-10 10 views
12

Obecnie używam C++ i Java w projekcie i chciałbym móc wysłać obiekt, który jest zawarty w C++ do mojego interfejsu Java, aby zmodyfikować go przez GUI, a następnie wysłać modyfikację z powrotem w C++.Zwracanie klasy C++ do Javy przez JNI

Do tej pory zwracałem albo nic, int, albo boolean do Javy przez interfejs JNI. Tym razem muszę wysłać obiekt przez interfejs. Udostępniłem podobną definicję klasy zarówno w C++, jak iw Javie. Chciałbym wiedzieć, jak utworzyć obiekt, dzięki czemu będę mógł go używać w Javie.

W C++ mam:

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

Ta funkcja będzie sprawdzony przez Java w celu uzyskania obiektu z C++ boku (obiekt jest zawarty w Singleton, łatwo dostępne).

Na koniec Java zrobić prosty wywołanie tej metody,

MyObject anObject = C_getMyObject(3); 

które powinny powrócić mi nowo utworzony obiekt.

Java aktualnie zwraca mi błąd UnsatisfiedLinkError, gdy wykonuję rzeczywiste połączenie. Co jest nie tak?

Odpowiedz

10

Oto rozwiązanie zdecydowałem użyć:

Po pierwsze, chciałbym stworzyć podobny obiekt w Javie. Następnie, z C++, zainicjowałbym to i przekazałbym mu wszystkie wartości.

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

Ale wtedy zdałem sobie sprawę, że to nie było bardzo przenośne i było trochę zbyt skomplikowane.

Zamiast tego, postanowiłem zwrócić ciąg, który Java będzie analizować i użyć do zainicjowania obiektu po jego stronie.

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

MyObject miałby konstruktor, który pobiera ciąg znaków. Uważam, że rozwiązanie jest proste i skuteczne.

4

Jeśli twoja klasa MyObject jest zdefiniowana w C++, nie będziesz mieć dostępu do jej metod w Javie. Chciałbym spróbować zdefiniować klasy otoki Java wokół obiektu 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); 

Jeśli można ekstrapolować API C zamiast, możesz spróbować JNA.

Twój UnsatisfiedLinkError może być dodatkowym znakiem w nazwie funkcji, jak napisano powyżej, lub może nie może obsłużyć wartości zwracanej przez MyObject?

4

Kolejnym narzędziem, na które powinieneś spojrzeć, jest SWIG. SWIG jest doskonałym narzędziem do generowania wrapperów w innych językach (takich jak Java, Python lub C#) dla istniejących obiektów C/C++. Wygeneruje automatyczne owijki Java wokół obiektów C/C++ i zrobi dla ciebie wszystkie ciężkie ćwiczenia JNI.

Używam go szeroko w Xuggler. Aby zobaczyć przykład, jeśli pobrać kod źródłowy Xuggler jest C++ object tutaj:

csrc/com/xuggle/xuggler/IStreamCoder.h 

zdefiniować plik interfejsu SWIG tutaj:

csrc/com/xuggle/xuggler/IStreamCoder.i 

i kiedy prowadzony przez Swig generuje Java przedmiot (który jest przechowywany tutaj)

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

następnie możemy uzyskać dostęp do obiektu z łatwością Java (dobrze, dodaję trochę ref liczenia rzeczy, ale to dość zaawansowany). Nadzieja, która pomaga.

Art

Powiązane problemy