Declarar Métodos Nativos

Esta página ilustra cómo declarar un método nativo en el lenguaje Java y cómo generar el correspondiente prototipo de función en C/C++.

El Lado Java

Nuestro primer ejemplo, Prompt.java, contiene un método nativo que acepta e imprime un String Java. El programa llama al método nativo, que espera por una entrada del usuario y luego devuelve la línea que el usuario a tecelado.

La clase Java Prompt contiene un método main que es utilizado para llamar al programa. Además, existe un método nativo getLine:

private native String getLine(String prompt);
Observa que las declaraciones para métodos nativos son casi identicas a las declaraciones de métodos normales de Java. Existen dos diferencias. Los métodos nativos deben tener la palabra clave native. Esta palabra clave informa al compilador Java que la implementación para este método se proporciona en otro lenguaje. También, la declaración del método nativo termina con un punto y coma, el símbolo de terminador de sentencia, porque no hay implementaciones para métodos nativos en los ficheros de clases del lenguaje Java.

El Lado del Lenguaje Nativo

Se deben declarar e implementar los métodos nativos en un lenguaje nativo, como C o C++. Antes de hacer esto, es útil generar un fichero de cabecera que contenga el prototipo de la función para la implementación del método nativo.

Compilamos el fichero Prompt.java y luego generamos el fichero .h. Primeros compilamos el fichero Prompt.java de esta forma:

javac Prompt.java
Una vez compilado satisfactoriamente y habiendo creado el fichero Prompt.class, podemos crear un fichero de cabecera al stilo JNI, especificando una opción -jni a javah:
javah -jni Prompt
Examinamos el fichero Prompt.h. Observa el prototipo de función para el método nativo getLine que declaramos en Prompt.java.
JNIEXPORT jstring JNICALL 
Java_Prompt_getLine(JNIEnv *, jobject, jstring);
La definición de la función del método nativo en el código de implementación debe corresponder con el prototipo de función generado en el fichero de cabecera. Siempre se debe incluir JNIEXPORT y JNICALL en los prototipos de función para métodos nativos. JNIEXPORT y JNICALL se aseguran de que el código fuente se compilará en plataformas como Win32 que requieren palabras claves especiales para funciones exportadas desde librerías de enlace dinámico.

Los nombres de los métodos nativos son una concatenación de los siguientes componentes:

(Observa que los nombres de los métodos nativos sobrecargados, además de los componentes anteriores, tienen un doble subrayado "__" añadido al nombre del método y seguido por la firma de argumentos).

Así, la implementación en código nativo para el método Prompt.getLine se convierte en Java_Prompt_getLine. (No existe nombre de paquete, porque la clase Prompt está en el paquete por defecto).

Cada método nativo tiene dos parámetros además de los que pongamos en la declaración en lenguaje Java. El primer parámetro, JNIEnv *, es el puntero al interface JNI. Este puntero a interface está organizado como una tabla de funciones, donde cada función JNI tiene un punto de entrada conocido en la tabla. Nuestros métodos nativos llaman a funciones específicas del JNI para acceder a objetos Java a través del puntero JNIEnv *. El parámetro jobject es una referencia al propio objeto (es como el puntero this en C++).

Y por último, observa que el JNI tiene un conjunto de tipos de nombres, como jobject y jstring, y cada tipo corresponde con un tipo del lenguaje Java. Todos esto se cubre en la página siguiente.


Ozito