Este capítulo está siendo desarrollado, puede contener errores.
Java provee la posibilidad de acceder a funciones desarrolladas en C a través de lo que se llama "métodos nativos". Actualmente existen dos tecnologías a través de las cuales podemos invocar funciones C desde nuestros programas Java. Estas son:
- JNI - "Java Native Interface" (la tecnología tradicional), y
- JNA - "Java Native Access"
En este capítulo desarrollaremos algunos ejemplos en ambas tecnologías con los objetivos de comprender como se utilizan y de poderlas comparar.
HolaMundo - JNI
Usar JNI es algo engorroso. A continuación voy a enumerar los pasos que hay que realizar para invocar a una función C que imprima "Hola Mundo" en la consola.
Si el lector considera que este ejemplo es demasiado complicado o se le complica seguirlo hasta el final le recomiendo que vaya directamente a ver la implementación desarrollada con JNA expuesta más abajo.
1 - Definir una clase Java con los métodos nativos
CLib.java (clase con métodos nativos)
1:
2:package demo.jni;
3:
4:public class CLib
5:{
6: // los metodos nativos no se desarrollan
7: public native void holaMundo();
8:}
9:
2 - Compilar el .java anterior y luego correr el comando javah para generar el .h con los headers C que se corresponden con los métodos nativos definidos en la clase.
javah -jni demo.jni.CLib
Debemos tener en cuenta que para ejecutar este comando desde la línea de comandos tenemos que tener seteado el PATH a %JAVA_HOME%\bin y debemos estar posicionados en el directorio padre del paquete demo o bien debemos tener seteado correctamente el CLASSPATH.
El comando javah debe generar el siguiente archivo:
demo_jni_CLib.h
1:/* DO NOT EDIT THIS FILE - it is machine generated */
2:#include <jni.h>
3:/* Header for class demo_jni_CLib */
4:
5:#ifndef _Included_demo_jni_CLib
6:#define _Included_demo_jni_CLib
7:#ifdef __cplusplus
8:extern "C" {
9:#endif
10:/*
11: * Class: demo_jni_CLib
12: * Method: holaMundo
13: * Signature: ()V
14: */
15:JNIEXPORT void JNICALL Java_demo_jni_CLib_holaMundo
16: (JNIEnv *, jobject);
17:
18:#ifdef __cplusplus
19:}
20:#endif
21:#endif
22:
3 - Programar en C la implementación del método nativo holaMundo utilizando el header que obtuvimos luego de correr el comando javah.
demoJNI.c
1:
2:#include<stdio.h>
3:#include<jni.h>
4:#include "demo_jni_CLib.h"
5:
6:JNIEXPORT void JNICALL Java_demo_jni_CLib_holaMundo (JNIEnv *env, jobject obj)
7:{
8: printf("Hola Mundo\n");
9:}
10:
4 - Compilar el código C y generar una DLL. Si usamos MinWG el comando será el siguiente:
gcc -c -I%JAVA_HOME\include -I%JAVA_HOME%\include\win32 demoJNI.c
gcc -shared -o demoJNI.dll demoJNI.o
Esto generara el archivo demoJNI.dll.
5 - Escribir un programa que instancie la clase CLib e invoque al método holaMundo.
Demo.java
1:
2:package demo.jni;
3:
4:public class Demo
5:{
6: public static void main(String[] args)
7: {
8: System.loadLibrary("demoJNI");
9: CLib clib = new CLib();
10: clib.holaMundo();
11: }
12:}
13:
Más información en: http://java.sun.com/docs/books/jni/html/start.html
Hola Mundo - JNA
El enfoque que provee JNA es mucho más intuitivo, simple y directo. Solo necesitamos descargar el archivo jna.jar.
1 - En JNA comenzamos por escribir el código C sin condicionarlo con ningún header extraño.
demoJNA.c
1:
2:#include <stdio.h>
3:void holaMundo()
4:{
5: printf("Hola Mundo\n");
6:}
7:
2 - El siguiente paso es crear una interface Java que defina el método holaMundo que "wrappea" a la función escrita en C.
CLib.java
1:
2:package demo.jna;
3:
4:import com.sun.jna.Library;
5:
6:public interface CLib extends Library
7:{
8: public void holaMundo();
9:}
10:
3 - Por último podemos escribir el programa principal que invoca al método holaMundo de la interface CLib.
Demo.java
1:
2:package demo.jna;
3:
4:import com.sun.jna.Native;
5:
6:public class Demo
7:{
8: public static void main(String[] args)
9: {
10: CLib clib= (CLib) Native.loadLibrary("demoJNA", CLib.class);
11: clib.holaMundo();
12: }
13:}
14:
Más información en: https://jna.dev.java.net/
.
6 comentarios:
Una curiosidad, ¿Qué herramienta utilizas para generar el código Java con syntax highlight que pones en tus mensajes?
Gracias.
Hola amigo, esta muy padre tu post :P bueno mi pregunta es la siguiente:
¿con JNA tambien puedo hacer uso tanto de archivos *.c como TAMBIEN DE librerias dinamicas (.dll)?
Esto lo pregunto por que vi que en tu post usaste JNA solo para implementar un archivo *.c
Muy bueno
gracias por el aporte XD!
sirvio de mucho ...
por si acaso aclaro q para JNA tmb se crea la dll y se pega en c:/windows/system32
y el programa es MinGW
entras con cmd a
C:\MinGW\bin
y pegas tu archivo *.c
y ejecutas los comandos q dice alli
gcc -c -I%JAVA_HOME\include -I%JAVA_HOME%\include\win32 archivo.c
//genera archivo.o
gcc -shared -o archivo1.dll archivo.o
//genera archivo1.dll
y claro Eclipse tiene a MinGW para convertir un archi.c a dll
pd:compartir experiencias es lo q hace a la web una red
mmmmchale no se que pasa que no me sale el ejemplo de jna!!!
el error lo tengo en:
Native.loadLibrary("demoJNA", CLib.class);
Digo no es un error de sintaxis ni nada solamente que cuando lo corro me dice que demoJNA no existe, sabes no se si lo copie mal o no se pero quiza es por que loanlirary necesita hacer una referencia a una libreria dinamica .dll y no a un codigo sin compilar de c++ como es el caso de demoJNA.c
Buenas que tal? Muy interesante este articulo, pero tengo un par de preguntas.
JNA es mucho mas sencillo que JNI, pero funciona con C++? habria forma de hacerlo funcionar, de manera que siga quedando mas sencillo de utilizar que JNI?
Desde ya muchas gracias!
Publicar un comentario