Cómo llamar a la función c desde Java. Parece que c está basado en el compilador.Llamada a la función c desde Java
Me gustaría llamar a la función C en Windows desde Java, y función GCC de Java también.
¿Alguna referencia?
Cómo llamar a la función c desde Java. Parece que c está basado en el compilador.Llamada a la función c desde Java
Me gustaría llamar a la función C en Windows desde Java, y función GCC de Java también.
¿Alguna referencia?
Echa un vistazo a Java Native Interface: Getting Started.
2,1 Descripción general
[...] escribir una sencilla aplicación Java que llama a una función C para imprimir "Hello World!". El proceso consta de los siguientes pasos:
Cree una clase (HelloWorld.java) que declare el método nativo. Use javac para compilar el archivo fuente HelloWorld, lo que da como resultado el archivo de la clase HelloWorld.class. El compilador javac se suministra con JDK o Java 2 versiones de SDK. Use
javah -jni
para generar un archivo de encabezado C (HelloWorld.h
) que contenga el prototipo de función para la implementación del método nativo . La herramienta java se proporciona con versiones de JDK o Java 2 SDK . Escriba la implementación 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 vinculador disponibles en el entorno de host. Ejecute el programa HelloWorld utilizando el intérprete de tiempo de ejecución de java. Tanto el archivo de clase (HelloWorld.class
) y la biblioteca nativa (HelloWorld.dll
olibHelloWorld.so
) se cargan en tiempo de ejecución. El resto de este capítulo explica estos pasos en el detalle .2,2 declarar el método nativo
Se empieza por escribir 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 clase HelloWorld comienza con la declaración del método nativo de impresión. Esto es seguido por un método principal que instancia 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.
Existen 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 es implementado en otro idioma. Además, la declaración de método nativo finaliza con un punto y coma, el símbolo de terminador de declaración, porque no hay implementación para métodos nativos en la clase . Implementaremos el método de impresión en un archivo C separado.
Antes de que se pueda invocar la impresión del método 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 invocando 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 para imprimir de la misma manera que que llamaría 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 compilar la clase HelloWorld
Después de haber definido la clase HelloWorld, guarde el código fuente en un archivo llamado HelloWorld.java. A continuación, compile el archivo fuente usando el compilador javac que viene con la versión 2 del SDK de Java JDK o:
javac HelloWorld.java
Este comando generará un archivo
HelloWorld.class
en el directorio actual.2.4 Crear archivo de cabecera del método nativo
A continuación usaremos la herramienta
javah
para generar un archivo de cabecera de estilo JNI que es útil en la aplicación del método nativo en C. Puede ejecutarjavah
en elHello-World
la clase de la siguiente manera:javah -jni HelloWorld
el nombre del archivo de cabecera es el nombre de la clase con un "
.h
" adjunta al final de la misma. El comando que se muestra arriba genera un archivo llamadoHelloWorld.h
. No enumeraremos el archivo de encabezado generado en su totalidad aquí. La parte más importante del archivo de cabecera 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);
ignorar el
JNIEXPORT
yJNICALL
macros por ahora. Puede haber notado que la implementación C del método nativo acepta dos argumentos aunque la declaración correspondiente del método nativo acepta sin 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
(algo así como el "this
" puntero en C++). Discutiremos cómo utilizar elJNIEnv
interfaz puntero y los argumentosjobject
más adelante en este libro, pero este simple ejemplo ignora ambos argumentos.2.5 Escribir la Implementación del Método Nativo
El archivo de cabecera de estilo JNI generada por
javah
le ayuda a escribir C o C++ para las implementaciones del método nativo. La función que escriba debe seguir el -prototipo especificado en el archivo de encabezado generado. Usted puede poner en práctica el métodoHello-World.print
en un archivo CHelloWorld.c
como sigue:#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 sencillo. Utiliza la función printf para mostrar la cadena "Hello World!" y luego regresa Como se mencionó anteriormente, se ignoran ambos argumentos, el puntero
JNIEnv
y la referencia al objeto.El programa C incluye tres archivos de cabecera:
jni.h
- Este fichero de cabecera proporciona información del código nativo necesita para llamar a funciones JNI. Al escribir métodos nativos, siempre debe incluir este archivo en sus archivos fuente C o C++.stdio.h
- El código snippet anterior también incluyestdio.h
porque utiliza la funciónprintf
.HelloWorld.h
- El archivo de encabezado que generó usandojavah
. Incluye el prototipo C/C++ para la funciónJava_HelloWorld_print
. 2.6 Compilar el C Fuente y crear una biblioteca nativaRecuerde que cuando se creó la clase
HelloWorld
en el archivoHelloWorld.java
, que incluyó una línea de código que carga un biblioteca nativa en el programa:System.loadLibrary("HelloWorld");
Ahora que está escrito todo el código C necesario , debe compilar
Hello-World.c
y compilar esta biblioteca nativa .Diferentes sistemas operativos admiten diferentes formas de compilar 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 indica al compilador C para generar una biblioteca compartida en lugar de un archivo normal de Solaris ejecutable. Debido a la limitación del ancho de página en este libro, , rompemos 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 construye una librería de enlace dinámico (DLL)HelloWorld.dll
usando el compilador de Visual C++ de Microsoft:cl -Ic:\java\include -Ic:\java\include\win32 -MD -LD HelloWorld.c -FeHelloWorld.dll
La opción
-MD
asegura queHelloWorld.dll
está vinculado con la biblioteca C multiprocesoWin32
. La opción-LD
indica al compilador de C que genere una DLL en lugar de un ejecutable regular de Win32. Por supuesto, tanto en Solaris como en Win32, usted necesita incluir las rutas de acceso que reflejan la configuración en su propia máquina .2.7 Ejecutar el Programa
En este punto, usted 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.Porque la clase
HelloWorld
contiene su propio método principal, puede ejecutar el programa en Solaris o Win32 de la siguiente manera:java HelloWorld
debería ver el siguiente resultado:
Hello World!
Es Es importante establecer correctamente la ruta de la biblioteca nativa para que se ejecute su programa. La ruta de la biblioteca nativa es una lista de directorios que la máquina virtual Java busca al cargar bibliotecas nativas. Si usted no tiene una ruta de biblioteca nativa estableció correctamente, entonces usted 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 reside en uno de los directorios de la ruta de biblioteca nativa. Si está ejecutando en un sistema Solaris, la variable de entorno
LD_LIBRARY_PATH
se usa 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 dos comandos siguientes en el estándar de shell (sh) o KornShell (ksh) para establecer la variableLD_LIBRARY_PATH
entorno adecuadamente:LD_LIBRARY_PATH=. export LD_LIBRARY_PATH
El equivalente mando en el shell C (csh) es el siguiente:
setenv LD_LIBRARY_PATH .
Si está ejecutando en un equipo Windows 95 o Windows NT máquina, asegúrese de que está en t
HelloWorld.dll
El directorio actual , o en un directorio que se enumera en la variable de entorno PATH .En Java 2 SDK 1.2 de liberación, también puede especificar la ruta de biblioteca nativa en la línea de comandos Java como una propiedad del sistema de la siguiente manera:
java -Djava.library.path=. HelloWorld
El "
-D
" opción de línea de comandos establece una propiedad del sistema plataforma Java. Establecer la propiedadjava.library.path
en ".
" indica a la máquina virtual Java que busque bibliotecas nativas en el directorio actual.
Los usuarios de Mac pueden ignorar los comandos de Solaris. Este blog me ayudó a terminar lo que ayudó a comenzar esta respuesta: http://nerdposts.blogspot.com/2010/10/jni-mac-os-x-simple-sample.html – cloudsurfin
En términos simples, solo asegúrese de cargar la biblioteca relevante que contiene la definición de función, cargar la biblioteca que sigue la especificación JNI y envolver la función objetivo desde la primera biblioteca, exponer métodos nativos de su clase Java y Usted debe ser bueno para ir.
Lo recomiendo contra raw JNI ya que contiene un montón de código repetitivo y terminará maldiciéndose a sí mismo si comienza a envolver una gran biblioteca C grande. De todos modos, siéntase libre de meterse en JNI cuando empiece, pero use algo como JNA en lo que respecta al trabajo real.
¿JNA es tan rápido como JNI? – Pacerier
En la categoría de "exótico", véase NestedVM, que compila la C a Mips, y ejecuta una Mips VM dentro de JVM.
usted las opciones incluyen:
Java Native Interface
véase: https://en.wikipedia.org/wiki/Java_Native_Interface
cita:
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, p. cuando la biblioteca de clases estándar de Java no es compatible con las características específicas de la plataforma o biblioteca de programas
Java Native Access
véase: https://en.wikipedia.org/wiki/Java_Native_Access
cita:
Java Native Access es una biblioteca desarrollada por la comunidad que proporciona a los programas Java fácil acceso a bibliotecas compartidas nativas sin usar Java Nat Interfaz.
JNR-FFI
véase: https://github.com/jnr/jnr-ffi
cita:
JNR-fi es una biblioteca Java para cargar bibliotecas nativas sin necesidad de escribir código JNI a mano, o usando herramientas como SWIG.
¿Entonces JNR diff JNA es? – Pacerier
Realizar pedido JNAerator. https://code.google.com/p/jnaerator/
es necesario proporcionar el código fuente y las definiciones del preprocesador etc.
Para hacer DLL de 64 bits compatibles Quitar "-MD" opción en las siguientes afirmaciones
"cl ic: \ java \ include -Ic: \ java \ include \ win32 -MD -LD HelloWorld.c -FeHelloWorld.dll "
Tengo una solución para este problema. Lo que necesita asegurarse es compilar el código utilizando un compilador de C++ de 64 bits para llamar a la función java que se ejecuta en el JRE de 64 bits. Junto con esto, debemos guardar la ruta del archivo dll creado en "Ruta" en "Variable de entorno".
Si se está empleando gcc de Windows y MinGW es posible que tenga la bandera adicional si usted está recibiendo UnsatisfiedLinkError para el 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
En primer lugar hacer garantizar a cargar su biblioteca nativa o un archivo .dll en la ruta de clase mediante el establecimiento de ruta en la propiedad java.library.path
a continuación, utilice System.loadLibrary()
Do not use .dll extension at the end.
Es posible que quiera mirar en JNI (Java Native Interface). –
Comenzaría con estos http://www.google.co.uk/search?q=JNI+tutorial –
Ok. Muchas gracias. – Wen