domingo, 12 de febrero de 2012

JNI, Eclipse y Win7 64 Bit

He redactado este tutorial como punto de partida para diseñar programas usando la herramienta JNI de java. Esta herramienta permite llamar funciones de lenguaje C, a través de una dll, desde una aplicación en Java.
Esto es útil ya que hay una gran cantidad de Hardware cuyas librerías de comunicación han sido desarrolladas en C (nosotros somos electrónicos). Sin embargo, dada la flexibilidad de programación de interfaces gráficas de usuario (GUIs) bajo Java, además de su potencial multiplataforma, la posibilidad de programar una aplicación que use Hardware bajo este lenguaje de programación no puede ser ignorada.
Para este tutorial usaré el sistema operativo de Microsoft Windows 7 de 64 bits,  los IDE de  Eclipse para Java y C, además del compilador Mingw; tanto el IDE de Java y C y el compilador serán de 64 bits. Pueden descargar Eclipse desde:


El compilador deberá ser descargado desde:


y deberán asegurarse de que están descargando la versión correcta. La siguiente imagen muestra el que yo descargué y usé para este tutorial.


Lo último que hay que descargar es el JDK (Java Development Kit) de la siguiente dirección:


Debo señalar que pueden encontrar la documentación del JNI fácilmente desde Google. De hecho, el ejemplo que estaré escribiendo es prácticamente el mismo que pueden encontrar en dicha documentación, sin embargo, en este tutoral además de escribir sobre el JNI, señalaré como configurar Eclilpse para compilar tanto la librería en C como la aplicación en Java.

Para empezar hay que descomprimir el compilador Mingw-64. Yo lo descomprimí en:

C:\mingw-w64

y los ejecutables se encuentran en:

C:\mingw-64\bin

este directorio lo utilizaremos cuando configuremos Eclipse.
Los IDEs de Java y C también hay que descomprimirlos, pero la gran ventaja es que no hay que instalarlos, sólo basta con descomprirmlos y ejecutarlos. Finalmente ejecutamos el JDK que hayamos descargado de Oracle para que éste se instale en el sistema. Usualmente en 

C:\Program Files\Java\...

Para empezar con el tutorial, vamos a crear un proyecto de Java en Eclipse y agregaremos una  clase llamada Main con la opción "public static void main(String[] args)" habilitada. La función que implementaremos en C únicamente imprimirá en consola una leyenda, asi que la llamaremos print. El código queda como muestra la imagen siguiente.


En la imagen se muestra la función que estará en C llamada print y el nombre de la librería *.dll. Además de dichas definiciones, debemos llamarla dentro de nuestro código mediante la instrucción "new Main().print();"
Ya que escribimos y salvamos el código, lo que debemos hacer es crear un Header a partir de este código que será usado por nuestro código en C. Para lograr esto, usaremos dos herramientas que son instaladas dentro del JDK: javac y javah, ambas contenidas dentro de la carpeta  ../bin del directorio de instalación:



EL código que escribimos anteriormente se guardará con el nombre Main.java y lo copiaremos dentro de la carpeta donde están los ejecutables de javac y javah. 
Una vez copiado, usaremos la consola de Windows para obtener el Header. La consola se encuentra en  Inicio->Programas-> Accesorios. Cuando localicen la consola, deberán ejecutarla como administradores, haciendo clic derecho sobre el nombre y escogiendo la opción como muestra la figura:

El siguiente paso es ir al directorio ..\bin y ejecutar las siguientes instrucciones:


La primera, genera un archivo llamado Main.class. La segunda genera el Header que necesitamos: Main.h, que contiene, entre otras cosas, el prototipo de la función que usaremos en el código en C:



Ahora tenemos que ir al IDE de Eclipse para C. Creamos un nuevo proyecto en C como Librería Compartida (Shared Library) y en el directorio donde se crea este proyecto, copiaremos el Main.h. Llamaremos el archivo JNIPrueba y la librería dll se llamará como hayamos nombrado el código en C agregando "lib" al principio, por lo tanto la librería será libJNIPrueba.dll. Ya que se trata de una librería compartida, no hay una función main(), sino que se trata de una función cuyo nombre será igual al del prototipo contenido en Main.h. El código en C queda como se muestra a continuación:


En la imagen anterior es muestra la función que imprime la leyenda "jni" la cual se llama igual que el prototipo contenido en Main.h. Noten como, aunque el nombre es el mismo, dentro del paréntesis se agregan los objetos *env y obj. Además de mostrar el código, muestro los dos Headers que debemos incluir: Main.h y jni.h. EL primero es el que copiamos anteriormente; el segundo se encuentra en el directorio del JDK en la carpeta include. Debemos configurar Eclipse para que encuentre este Header yéndonos a Project->Properties y agregando dos directorios en Includes, dentro de GCC C Compiler en C/C++-> Settings como muestra la figura:



Ahora para compilar, debemos configurar a Eclipse para que use el Mingw de 64 bits. Para lograr esto, primero debemos escribir el nombre del compilador en la opción "command" dentro de GCC C Compiler y MinGW C Linker como se muestra a continuación:




Finalmente debemos incluir en el PATH de Eclipse el directorio donde se encuentran estos compiladores:



Ahora podemos compilar y si todo ha salido bien, se generará la librería libJNIPrueba.dll.

Ahora que tenemos la librería regresamos al código en Java. Eclipse no puede encontrar la dll hasta que nosotros le digamos donde está, por lo tanto hay que configurarlo agregando el directorio de la librería en las propiedades del proyecto como se muestra en la figura siguiente:



Para concluir, después de correr el programa deberá aparecer en la consola la leyenda "jni":


Espero haya sido de utilidad este tutorial. Más adelante escribiré como comunicarse con dispositivos USB usando esta herramienta.
Cualquier duda o comentario, no duden en escribirme!!!