Bloque externo "Java" en GCC
c++ jni (2)
GCJ proporciona dos interfaces nativas para Java: JNI con C y CNI con C ++. Dado que el ejemplo que usted cita usa una clase, tiene que referirse a este último. La documentación de CNI sobre interfaces solo describe cómo acceder a las interfaces descritas en Java desde el código C ++. Su ejemplo parece funcionar al revés: una clase escrita en C ++ a la que se puede acceder desde Java y sirve como interfaz de Java.
Pero hay muy pocos detalles disponibles sobre esto, por lo que la prueba y el error serán una forma de experimentar con esto, y observar las fuentes reales de GCC sería otra. Si desea ver un ejemplo del bloque extern "Java"
y del atributo java_interface
, eche un vistazo a java/lang/Readable.h
. Contiene la representación en C ++ de la interfaz Java java.lang.Readable
. Como indica la primera línea de ese archivo, se genera por máquina. Así que probablemente la razón por la que hay tan poca documentación es porque no se supone que no debas escribir estas cosas tú mismo. Es solo un detalle de cómo GCJ implementa CNI. Y al observar más de cerca el archivo anterior, parece que incluso violan su propia documentación, ya que Readable.h
tiene el atributo fuera del bloque extern
, en contraste con el fragmento que citó.
Encontré una feature interesante en la documentación de GCC para C ++:
interfaz_java
Este atributo de tipo informa a C ++ de que la clase es una interfaz Java. Solo se puede aplicar a las clases declaradas dentro de un bloque "Java" externo . Las llamadas a los métodos declarados en esta interfaz se enviarán mediante el mecanismo de la tabla de interfaz de GCJ, en lugar del envío de la tabla virtual regular.
Según tengo entendido se verá algo como esto:
extern "Java" {
class NativeClass __attribute__((java_interface)) {
//Implementation on native methods goes here.
}
}
¿Alguien sabe detalles sobre esto? ¿Cómo llamar a los métodos de NativeClass desde Java? Tal vez alguien lo intentó en la vida real?
La primera vez que conocí este tipo de bloque no fue para "java" sino para "C", así que creo que es el mismo interés. El bloque definido por:
extern "Java"
{
// some java definition
}
se utiliza para especificar a GCC que este bloque es una interfaz Java. Se usa para describir qué tipo de mutilación se usa para definir la clase. El nombre mangling lo utiliza gcc para generar el nombre de la función por parámetros, etc. Más información aquí: http://www.agner.org/optimize/calling_conventions.pdf Entonces, utiliza un extern "Java"
cuando importa el código Java. con él puede llamarlo juste como cualquier función en C / C ++ sin especificar el nombre destrozado. Mi único uso fue para un dll con algunas funciones de C definidas en, cargado en un código de C ++, por lo que utilizo una "C" externa para especificar a GCC que la definición de esta función no utiliza la manipulación de nombres. Bueno, ahora, cómo llamar a un método nativo en java porque todo en java es método, todo es objeto, no hay función. Primero, debe describir su clase en java, todas las funciones que desea realizar en el lenguaje nativo deben definirse como nativas: private native void print();
por ejemplo. En segundo lugar, de nuevo en el encabezado de su código nativo, debe definir el método siguiendo la nomenclatura:
extern "Java"
{
JNIEXPORT YourReturnType JNICALL Java_ClassName_MethodName (JNIEnv* env, jobject obj);
}
Al menos, todos los métodos deben tener el mismo aspecto, ya que JNI enviará un puntero JNIEnv y un objeto que estará "esto" en el método; si tiene otros argumentos, deben entregarse después de los 2 conceptos básicos. Finalmente, solo tienes que implementar todos los métodos en un archivo de código nativo, siempre siguiendo la norma, como:
JNIEXPORT void JNICALL Jave_Printer_print(JNIEnv* env, jobject obj)
{
printf("Hello world");
}
Ahora puede crear un objeto de impresora en Java y llamar al método de impresión definido como nativo. Espero haber respondido a tu pregunta.