Implementación de clases java con métodos nativos escritos en C++ (JNI)

Indice


1.Introduccion………………………………………………………………………………………………………………………… 2

2.Declaracion de la clase nativa…………………………………………………………………………………………………. 3

3.Implementacion de los metodos de la DLL…………………………………………………………………………………. 4

3.1.Nomenclatura de los metodos………………………………………………………………………………………….. 4

3.2.Convencion de llamada…………………………………………………………………………………………………… 4

3.3.Manipulacion de objetos………………………………………………………………………………………………….. 4

3.4.Manejo de excepciones………………………………………………………………………………………………….. 4

3.4.1.Capturar excepciones lanzadas por la parte Java……………………………………………………………. 4

3.4.2.Lanzar excepciones a la parte Java…………………………………………………………………………….. 5

4.Ejemplo de implementación……………………………………………………………………………………………………. 6

4.1.Parte Java……………………………………………………………………………………………………………………. 6

4.2.Parte C++……………………………………………………………………………………………………………………. 7

4.3.Paso a paso………………………………………………………………………………………………………………… 8

5.Apendice………………………………………………………………………………………………………………………….. 11

5.1.Secuencias de escape en los nombres de funcion……………………………………………………………….. 11

5.2.Signaturas de funcion……………………………………………………………………………………………………. 11

5.3.Equivalencia de tipos primitivos……………………………………………………………………………………….. 12

5.4.Equivalencia de tipos compuestos……………………………………………………………………………………. 12


1.               Introduccion

El objetivo de este tutorial es mostrar como se puede implementar una clase Java con metodos nativos escritos en C++ y contenidos en una DLL de Windows. Se puede extrapolar facilmente a Unix, generando librerias compartidas de Unix (normalmente ficheros con extension .so) en vez de DLLs.

El mecanismo JNI de Java viene incluido con cualquier JDK de Sun y consiste en unos ficheros .h que hay en el directorio include del JDK. Dichos ficheros .h definen la interfaz entre nuestra DLL nativa y la JVM.

Para crear una clase Java con metodos nativos solo hay que marcar los metodos de la clase con la palabra native y, despues, implementarlos en la DLL siguiendo una convenciones sencillas.

A la hora de ejecutar solo es necesario que nuestra clase Java carque la DLL con los metodos nativos mediante una llamada a System.loadLibrary. La DLL se buscara en el PATH de Windows y en todos los directorios apuntados por la propiedad del sistema Java llamada java.library.path.

Este tutorial tiene dos capitulos genericos (2 y 3) que explican como se implementan los metodos nativos, un capitulo 4 con un ejemplo, y un apendice con referencias extraidas de la documentacion del JDK 5.0 de Sun.

2.               Declaracion de la clase nativa

Lo primero que tenemos que hacer es crear un fichero .java con la definicion de la clase como si fuesemos a escribir una clase Java normal. Todos los metodos que esten implementados en la DLL nativa deben llevar el prefijo native.

Además, hay que definir el constructor estatico de la clase y, dentro de el, llamar a System.loadLibrary para cargar la DLL que implementara los metodos nativos.

Ejemplo:

package autentia;  

 

class Cls

{

     // Metodo implementado nativamente

     native double f(int i, String s);

 

     // Inicializacion de la clase

     static

     {

         // Cargar la DLL que implementa la clase

         System.loadLibrary(“pkg_autentia”);

     }

}

 

La DLL se puede llamar como queramos, no hay ninguna restriccion sobre el nombre. Lo importante son los nombres de los metodos.

Este .java hay que compilarlo y nos dara un .class que, al usarlo, cargara la DLL y llamara a los metodos nativos. Si no se carga la DLL, la JVM lanzara una excepcion UnsatisfiedLinkError al llamar a los metodos nativos.

3.               Implementacion de los metodos de la DLL

3.1.        Nomenclatura de los metodos

Los nombres de los metodos deben seguir una convención predefinida:

         Metodos sobrecargados: Java_<clase cualificada>_<nombre del metodo>__<signatura de los argumentos>

         Metodos unicos: Java_<clase cualificada>_<nombre del metodo>__<signatura de los argumentos>

Existen ciertas secuencias de escape para los nombres de los metodos que estan listadas en el apéndice. Asimismo, se puede consultar en el mismo apéndice una explicacion de como se compone la signatura de los argumentos. La signatura describe los argumentos que recibe el metodo de forma inequivoca y es necesaria puesto que, debido a la sobrecarga, metodos con el mismo nombre pueden recibir distintos argumentos.

3.2.        Convencion de llamada

La convencion de llamada de los argumentos implementados nativamente es la siguiente:

         Para Win32 se usa la convencion de llamada __stdcall (PASCAL).

         Para Unix se usa la convencion de llamada __cdecl (C).

         Parametros: