descargar - javac install
Llamar a la funciĆ³n c desde Java (11)
Comprobación JNAerator. https://code.google.com/p/jnaerator/
Debe proporcionar el código fuente y las definiciones del preprocesador, etc.
Cómo llamar a la función c desde Java. Parece que c está basado en compilador.
Me gustaría llamar a la función C en Windows desde Java, y la función GCC desde Java también.
¿Alguna referencia?
Eche un vistazo a la interfaz nativa de Java: Primeros pasos .
2.1 Resumen
[...] escriba una aplicación Java simple que llame a una función de C para imprimir "Hello World!". El proceso consta de los siguientes pasos:
Cree una clase (HelloWorld.java) que declare el método nativo. Utilice javac para compilar el archivo fuente HelloWorld, lo que da como resultado el archivo de clase HelloWorld.class. El compilador javac se suministra con las versiones de JDK o Java 2 SDK. Utilice
javah -jni
para generar un archivo de cabecera C (HelloWorld.h
) que contiene la función prototipo para la implementación del método nativo. La herramienta javah se proporciona con las versiones JDK o Java 2 SDK. Escriba la implementación en C (HelloWorld.c
) del método nativo. Compile la implementación de C en una biblioteca nativa, creandoHello-World.dll
olibHello-World.so
. Utilice el compilador de C y el enlazador disponibles en el entorno host. Ejecute el programa HelloWorld utilizando el intérprete de tiempo de ejecución de Java. Tanto el archivo de clase (HelloWorld.class
) como la biblioteca nativa (HelloWorld.dll
olibHelloWorld.so
) se cargan en tiempo de ejecución. El resto de este capítulo explica estos pasos en detalle.2.2 Declarar el método nativo
Comienzas escribiendo el siguiente programa en el lenguaje de programación Java. El programa define una clase llamada HelloWorld que contiene un método nativo, imprimir.
class HelloWorld { private native void print(); public static void main(String[] args) { new HelloWorld().print(); } static { System.loadLibrary("HelloWorld"); } }
La definición de la clase HelloWorld comienza con la declaración del método nativo de impresión. A esto le sigue un método principal que crea una instancia de la clase Hello-World e invoca el método nativo de impresión para esta instancia. La última parte de la definición de clase es un inicializador estático que carga la biblioteca nativa que contiene la implementación del método nativo de impresión.
Hay dos diferencias entre la declaración de un método nativo, como la impresión y la declaración de métodos regulares en el lenguaje de programación Java. Una declaración de método nativo debe contener el modificador nativo. El modificador nativo indica que este método se implementa en otro idioma. Además, la declaración del método nativo se termina con un punto y coma, el símbolo terminador de la declaración, porque no hay implementación para los métodos nativos en la clase en sí. Implementaremos el método de impresión en un archivo C separado.
Antes de poder llamar al método de impresión nativo, se debe cargar la biblioteca nativa que implementa la impresión. En este caso, cargamos la biblioteca nativa en el inicializador estático de la clase
HelloWorld
. La máquina virtual Java ejecuta automáticamente el inicializador estático antes de invocar cualquier método en la claseHelloWorld
, asegurando así que la biblioteca nativa se carga antes de llamar al método nativo de impresión.Definimos un método principal para poder ejecutar la clase
HelloWorld
.Hello-World.main
llama al método nativo imprimir de la misma manera que lo haría con un método normal.
System.loadLibrary
toma un nombre de biblioteca, localiza una biblioteca nativa que corresponde a ese nombre y carga la biblioteca nativa en la aplicación. Discutiremos el proceso de carga exacto más adelante en el libro. Por ahora simplemente recuerde que para queSystem.loadLibrary("HelloWorld")
tenga éxito, necesitamos crear una biblioteca nativa llamadaHelloWorld.dll
en Win32, olibHelloWorld.so
en Solaris.2.3 Compila la clase HelloWorld
Una vez que haya definido la clase HelloWorld, guarde el código fuente en un archivo llamado HelloWorld.java. Luego, compile el archivo de origen utilizando el compilador javac que viene con la versión JDK o Java 2 SDK:
javac HelloWorld.java
Este comando generará un archivo
HelloWorld.class
en el directorio actual.2.4 Crear el archivo de encabezado de método nativo
A continuación, usaremos la herramienta
javah
para generar un archivo de encabezado de estilo JNI que es útil cuando se implementa el método nativo en C. Puede ejecutarjavah
en la claseHello-World
la siguiente manera:
javah -jni HelloWorld
El nombre del archivo de encabezado es el nombre de la clase con un "
.h
" anexado al final. El comando que se muestra arriba genera un archivo llamadoHelloWorld.h
. No listaremos el archivo de encabezado generado en su totalidad aquí. La parte más importante del archivo de encabezado es el prototipo de función paraJava_HelloWorld_print
, que es la función C que implementa el método HelloWorld.print:
JNIEXPORT void JNICALL Java_HelloWorld_print (JNIEnv *, jobject);
Ignore las macros
JNIEXPORT
yJNICALL
por ahora. Es posible que haya notado que la implementación en C del método nativo acepta dos argumentos, aunque la declaración correspondiente del método nativo no acepta argumentos. El primer argumento para cada implementación de método nativo es un puntero de interfazJNIEnv
. El segundo argumento es una referencia al objetoHelloWorld
sí (algo así como el puntero "this
" en C ++). Discutiremos cómo usar el puntero de la interfazJNIEnv
y los argumentos del proyecto de trabajo más adelante en este libro, pero este ejemplo simple ignora ambos argumentos.2.5 Escribir la implementación del método nativo
El archivo de encabezado de estilo JNI generado por
javah
ayuda a escribir implementaciones en C o C ++ para el método nativo. La función que escriba debe seguir el logotipo especificado en el archivo de encabezado generado. Puede implementar el métodoHello-World.print
en un archivo CHelloWorld.c
siguiente manera:
#include <jni.h> #include <stdio.h> #include "HelloWorld.h" JNIEXPORT void JNICALL Java_HelloWorld_print(JNIEnv *env, jobject obj) { printf("Hello World!/n"); return; }
La implementación de este método nativo es sencilla. Utiliza la función printf para mostrar la cadena "Hello World!" y luego vuelve. Como se mencionó anteriormente, ambos argumentos, el puntero
JNIEnv
y la referencia al objeto, se ignoran.El programa C incluye tres archivos de encabezado:
jni.h
: este archivo de encabezado proporciona información que el código nativo necesita para llamar a las funciones JNI. Al escribir métodos nativos, siempre debe incluir este archivo en sus archivos de origen C o C ++.stdio.h
: el fragmento de código anterior también incluyestdio.h
porque utiliza la funciónprintf
.HelloWorld.h
: el archivo de encabezado quejavah
usandojavah
. Incluye el prototipo C / C ++ para la funciónJava_HelloWorld_print
. 2.6 Compilar la fuente C y crear una biblioteca nativaRecuerde que cuando creó la clase
HelloWorld
en el archivoHelloWorld.java
, incluyó una línea de código que cargaba una biblioteca nativa en el programa:
System.loadLibrary("HelloWorld");
Ahora que se ha escrito todo el código C necesario, debe compilar
Hello-World.c
y construir esta biblioteca nativa.Diferentes sistemas operativos soportan diferentes formas de construir bibliotecas nativas. En Solaris, el siguiente comando crea una biblioteca compartida llamada libHello-World.so:
cc -G -I/java/include -I/java/include/solaris HelloWorld.c -o libHelloWorld.so
La opción -G le indica al compilador de C que genere una biblioteca compartida en lugar de un archivo ejecutable normal de Solaris. Debido a la limitación del ancho de la página en este libro, dividimos la línea de comando en dos líneas. Debe escribir el comando en una sola línea o colocar el comando en un archivo de script. En
Win32
, el siguiente comando crea una biblioteca de enlace dinámico (DLL)HelloWorld.dll
utilizando el compilador de Microsoft Visual C ++:
cl -Ic:/java/include -Ic:/java/include/win32 -MD -LD HelloWorld.c -FeHelloWorld.dll
La opción
-MD
garantiza queHelloWorld.dll
esté vinculado con la biblioteca C multiproceso deWin32
. La opción-LD
indica al compilador de C que genere una DLL en lugar de un ejecutable normal de Win32. Por supuesto, tanto en Solaris como en Win32 debe colocar las rutas de inclusión que reflejen la configuración en su propia máquina.2.7 Ejecutar el programa
En este punto, tiene los dos componentes listos para ejecutar el programa. El archivo de clase (
HelloWorld.class
) llama a un método nativo, y la biblioteca nativa (Hello-World.dll
) implementa el método nativo.Debido a que la clase
HelloWorld
contiene su propio método principal, puede ejecutar el programa en Solaris o Win32 de la siguiente manera:
java HelloWorld
Deberías ver el siguiente resultado:
Hello World!
Es importante establecer la ruta de la biblioteca nativa correctamente para que su programa se ejecute. La ruta de la biblioteca nativa es una lista de directorios que la máquina virtual de Java busca cuando carga bibliotecas nativas. Si no tiene una ruta de biblioteca nativa configurada correctamente, verá un error similar al siguiente:
java.lang.UnsatisfiedLinkError: no HelloWorld in library path at java.lang.Runtime.loadLibrary(Runtime.java) at java.lang.System.loadLibrary(System.java) at HelloWorld.main(HelloWorld.java)
Asegúrese de que la biblioteca nativa resida en uno de los directorios en la ruta de la biblioteca nativa. Si está ejecutando en un sistema Solaris, la
LD_LIBRARY_PATH
entornoLD_LIBRARY_PATH
se utiliza para definir la ruta de la biblioteca nativa. Asegúrese de que incluya el nombre del directorio que contiene el archivolibHelloWorld.so
. Si el archivolibHelloWorld.so
está en el directorio actual, puede emitir los siguientes dos comandos en el shell estándar (sh) o KornShell (ksh) para configurar laLD_LIBRARY_PATH
entornoLD_LIBRARY_PATH
correctamente:
LD_LIBRARY_PATH=. export LD_LIBRARY_PATH
El comando equivalente en el shell C (csh o tcsh) es el siguiente:
setenv LD_LIBRARY_PATH .
Si está ejecutando en una máquina con Windows 95 o Windows NT, asegúrese de que
HelloWorld.dll
esté en el directorio actual o en un directorio que aparezca en la variable de entorno PATH.En la versión Java 2 SDK 1.2, también puede especificar la ruta de la biblioteca nativa en la línea de comandos java como una propiedad del sistema de la siguiente manera:
java -Djava.library.path=. HelloWorld
La opción de línea de comando "
-D
" establece una propiedad del sistema de la plataforma Java. La configuración de la propiedadjava.library.path
en ".
"java.library.path
a la máquina virtual Java que busque bibliotecas nativas en el directorio actual.
En la categoría "exótica", vea NestedVM, que compila de C a Mips y ejecuta una máquina virtual de Mips dentro de JVM.
En términos simples, solo asegúrese de cargar la biblioteca relevante que contiene la definición de la función, cargue la biblioteca que sigue la especificación JNI y envuelva la función de destino de la primera biblioteca, exponga los métodos nativos de su clase de Java y debería estar listo .
Lo recomendaría contra JNI en bruto, ya que contiene una gran cantidad de código de repetición y terminaría maldiciéndose a sí mismo si comienza a envolver una gran biblioteca de C. De todos modos, siéntase libre de meterse en JNI al comenzar, pero use algo como JNA cuando se trata de trabajo real.
Para hacer una dll compatible de 64 bits, elimine la opción "-MD" de la siguiente declaración
"cl -Ic: / java / include -Ic: / java / include / win32 -MD -LD HelloWorld.c -FeHelloWorld.dll"
Primero asegúrese de cargar la biblioteca nativa o el archivo .dll en la ruta de clase estableciendo la ruta en la propiedad java.library.path
Luego usa System.loadLibrary()
Do not use .dll extension at the end.
Si está utilizando Windows y MinGW gcc, es posible que necesite un indicador adicional si está obteniendo UnsatisfiedLinkError para un método específico en lib:
gcc -D_JNI_IMPLEMENTATION_ -Wl,--kill-at -I"%JAVA_HOME%"/include -I"%JAVA_HOME%"/include/win32 BestCode.c -shared -o BestCode.dll
Sus opciones incluyen:
Interfaz nativa de Java
ver: https://en.wikipedia.org/wiki/Java_Native_Interface
citar:
JNI permite a los programadores escribir métodos nativos para manejar situaciones cuando una aplicación no puede escribirse completamente en el lenguaje de programación Java, por ejemplo, cuando la biblioteca de clases estándar de Java no admite las funciones específicas de la plataforma o la biblioteca de programas
Acceso nativo de Java
vea: https://en.wikipedia.org/wiki/Java_Native_Access
citar:
Java Native Access es una biblioteca desarrollada por la comunidad que proporciona a los programas de Java un acceso fácil a las bibliotecas compartidas nativas sin utilizar la interfaz nativa de Java.
JNR-FFI
ver: https://github.com/jnr/jnr-ffi
citar:
jnr-ffi es una biblioteca java para cargar bibliotecas nativas sin escribir el código JNI a mano o usar herramientas como SWIG.
Tengo una solución para este problema. Lo que debe asegurarse es que está compilando el código utilizando el compilador c ++ de 64 bits para llamar a la función java que se ejecuta en JRE de 64 bits. Junto con ello, debemos guardar la ruta del archivo dll creado en "Ruta" en "Variable de entorno".
dio una respuesta muy elaborada, pero creo que también vale la pena revisar este sitio web y obtendrá todas sus respuestas esenciales allí:
http://www.ntu.edu.sg/home/ehchua/programming/java/javanativeinterface.html
Explica cómo llamar a un programa usando JNI:
- Para los lenguajes C y C ++ o una mezcla de ambos.
- JNI sin ningún parámetro, primitivas, cadenas o matriz de primitivas
- Acceso a variables de objeto, métodos de instancias de devolución de llamada y mucho más.