2009-11-10 26 views
12

Actualmente estoy usando tanto C++ como Java en un proyecto y me gustaría poder enviar un objeto que está contenido en C++ a mi interfaz Java para modificarlo a través de una GUI y luego enviar la modificación de vuelta en C++.Devolver una clase C++ a Java a través de JNI

Hasta ahora he estado devolviendo nada, un int o un booleano a Java a través de la interfaz JNI. Esta vez tengo que enviar un objeto a través de la interfaz. He hecho disponible una definición de clase similar tanto en C++ como en Java. Me gustaría saber cómo crear un objeto para poder usarlo en Java.

En C++ que tienen:

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

Esta función se obtendría llamado por Java con el fin de conseguir el objeto de lado el C++ (el objeto está contenida en un producto único, de fácil acceso).

En el extremo de Java, hago una llamada simple a este método,

MyObject anObject = C_getMyObject(3); 

que me debe devolver el objeto recién creado.

Java actualmente me devuelve un UnsatisfiedLinkError cuando realizo la llamada real. ¿Qué está mal?

Respuesta

10

Aquí está la solución he optado por utilizar:

En primer lugar, me gustaría crear un objeto similar en Java. Luego, desde C++ lo instanciaría y pasaría todos los valores.

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

Pero luego me di cuenta de que esto no era muy portátil y era demasiado complicado.

En su lugar, decidí devolver una cadena que Java analizaría y usaría para inicializar el objeto de su lado.

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

MyObject tendría un constructor que toma una cadena. Creo que la solución es simple y efectiva.

4

Si su clase MyObject se define en C++, no podrá acceder a sus métodos en Java. Que iba a tratar de definir una clase contenedora de Java alrededor de su objeto 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); 

Si se puede extrapolar una API C en lugar, puede intentar JNA.

Su UnsatisfiedLinkError puede ser el carácter adicional en el nombre de su función como se escribió anteriormente, o tal vez no puede manejar el valor de retorno MyObject?

4

Otra herramienta que debe consultar es SWIG. SWIG es una gran herramienta para generar envoltorios en otros lenguajes (como Java, Python o C#) para objetos C/C++ existentes. Generará contenedores Java automáticos alrededor de objetos C/C++, y hará todo el trabajo JNI pesado por usted.

Lo uso ampliamente en Xuggler. Para ver un ejemplo, si se descarga el código fuente Xuggler hay un objeto de C++ aquí:

csrc/com/xuggle/xuggler/IStreamCoder.h 

que definen un archivo de interfaz SWIG aquí:

csrc/com/xuggle/xuggler/IStreamCoder.i 

Y cuando se ejecuta a través trago que genera una aplicación Java objeto (que se almacena aquí)

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

a continuación, puede acceder a ese objeto de Java con facilidad (así, añado algunos ref contando cosas, pero eso es bastante avanzado). Espero que ayude.

Arte

Cuestiones relacionadas