20 julio, 2009

Acceso a Métodos Nativos (JNI vs. JNA)

.

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"
Si bien ambas permiten acceder a funciones C desde Java, la metodología de trabajo es muy diferente. JNI es extremadamente más complejo que JNA.

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/












.

23 julio, 2008

Reestructurando el Blog

.
Estimado lector, a partir del día de la fecha el blog HolaMundo.java comenzará a ser reestructurado (valga la paradoja).
Por favor, disculpe las molestias.

Pablo.


PROGRESO 68%.....
(6/Julio/2009).

PROGRESO 60%.....
(30/Abril/2009)

Falta poco... solo un poco más de paciencia...
(29/Diciembre/2008)

Este es el responsable de la demora en la reestructuración del blog:

Las quejas por favor remitirlas a OctavianitoSZ.
Gracias.

Felíz 2009,
Pablo.
.