Appeler la fonction c à partir de Java


Comment appeler la fonction c à partir de Java. Il semble que c soit basé sur le compilateur.

Je voudrais appeler la fonction C dans Windows à partir de Java, et GCC fonction fron Java aussi.

Toute référence?

Author: Wen, 2011-05-11

10 answers

Regardez Java Native Interface: prise en main.

2.1 Aperçu

[...] écrivez une application Java simple qui appelle une fonction C à imprimer "Bonjour Tout Le Monde!". Le processus comprend les étapes suivantes:

Créer une classe (HelloWorld.java) qui déclare la méthode native. Utiliser javac pour compiler le fichier source HelloWorld, résultant en la classe fichier HelloWorld.classe. Le compilateur javac est fourni avec JDK ou Java 2 SDK publier. Utilisez javah -jni pour générer un fichier d'en-tête C (HelloWorld.h) contenant le prototype de fonction pour la méthode native application. L'outil javah est fourni avec JDK ou Java 2 SDK publier. Ecrire l'implémentation C (HelloWorld.c) du natif méthode. Compiler l'implémentation C dans une bibliothèque native, en créant Hello-World.dll ou libHello-World.so. Utilisez le compilateur C et l'éditeur de liens disponible sur l'hôte de l'environnement. Exécutez le programme HelloWorld en utilisant l'interpréteur d'exécution java. Les deux fichiers de classe (HelloWorld.class) et la bibliothèque native (HelloWorld.dll ou libHelloWorld.so) sont chargés au moment de l'exécution. Le reste de ce chapitre explique ces étapes dans détail.

2.2 Déclarer la méthode native

Vous commencez par écrire le programme suivant dans la programmation Java langue. Le programme définit une classe nommée HelloWorld qui contient méthode native, imprimer.

class HelloWorld {
    private native void print();

    public static void main(String[] args) {
        new HelloWorld().print();
    }

    static {
        System.loadLibrary("HelloWorld");
    }
}

La définition de la classe HelloWorld commence par la déclaration de la méthode native print. Ceci est suivi d'un principal méthode instancie la classe Hello-World et appelle la méthode print native pour cette instance. La dernière partie de la définition de classe est une statique initialiseur qui charge la bibliothèque native contenant le implémentation de la méthode print native.

, Il existe deux différences entre la déclaration d'une méthode native tels que print et la déclaration des méthodes régulières dans le Java langage de programmation. Une déclaration de méthode native doit contenir natif modificateur. Le modificateur natif indique que cette méthode est implémenté dans une autre langue. En outre, la déclaration de méthode native est terminé par un point-virgule, le symbole de terminaison de l'instruction, parce qu'il n'y a pas d'implémentation pour les méthodes natives dans la classe lui-même. Nous allons implémenter la méthode d'impression dans un fichier C séparé.

Avant que la méthode native print puisse être appelée, la bibliothèque native qui implements print doit être chargé. Dans ce cas, nous chargeons le natif bibliothèque dans l'initialiseur statique de la HelloWorld classe. Java la machine virtuelle exécute automatiquement l'initialiseur statique avant invoquant toutes les méthodes de la classe HelloWorld, garantissant ainsi que le la bibliothèque native est chargée avant l'appel de la méthode print native.

Nous définissons une méthode principale pour pouvoir exécuter la classe HelloWorld. Hello-World.main appelle la méthode native print de la même manière que cela appellerait une méthode régulière.

System.loadLibrary prend un nom de bibliothèque, localise un natif bibliothèque correspond à ce nom, et charge la bibliothèque native dans le application. Nous discuterons du processus de chargement exact plus tard dans la livre. Pour l'instant rappelez vous simplement que pour {[27] } pour réussir, nous devons créer un bibliothèque native appelée HelloWorld.dll sur Win32, ou libHelloWorld.so sur Solaris.

2.3 Compiler la classe HelloWorld

Après avoir défini la classe HelloWorld, enregistrez le code source dans un fichier appelé HelloWorld.Java. Puis compilez la source fichier à l'aide de la compilateur javac fourni avec la version du SDK JDK ou Java 2:

 javac HelloWorld.java

Cette commande va générer un HelloWorld.class fichier dans le répertoire courant.

2.4 Créer le fichier d'en-tête de méthode natif

Ensuite, nous utiliserons l'outil javah pour générer un fichier d'en-tête de style JNI c'est utile lors de l'implémentation de la méthode native en C. Vous pouvez exécuter javah sur la classe Hello-World comme suit:

  javah -jni HelloWorld

Le nom du fichier d'en-tête est le nom de la classe avec un ".h" ajouté à la fin de celui-ci. La commande ci-dessus génère un fichier nommé HelloWorld.h. Nous ne listerons pas le produit fichier d'en-tête dans son intégralité ici. La partie la plus importante de la le fichier d'en-tête est le prototype de fonction pour Java_HelloWorld_print, qui est la fonction C qui implémente HelloWorld.méthode d'impression:

 JNIEXPORT void JNICALL   Java_HelloWorld_print (JNIEnv *, jobject);

Ignorez les macros JNIEXPORT et JNICALL pour l'instant. Vous avez peut-être remarqué que l'implémentation C de la méthode native accepte deux arguments quoique la déclaration de la méthode native accepte pas d'arguments. Le premier argument pour chaque méthode native l'implémentation est un pointeur d'interface JNIEnv. Le deuxième argument est un référence à l'objet HelloWorld lui-même (un peu comme le " this" pointeur en C++). Nous allons discuter de la façon d'utiliser l'interface JNIEnv pointeur et les arguments jobject plus tard dans ce livre, mais ce simple exemple ignore les deux arguments.

2.5 Écrire l'implémentation de la méthode native

Le fichier d'en-tête de style JNI généré par javah vous aide à écrire C ou Implémentations C++ pour la méthode native. La fonction que vous écrivez doit suivre le prototype spécifié dans le fichier d'en-tête généré. Vous peut implémenter la méthode Hello-World.print dans un fichier C HelloWorld.c comme suit:

#include <jni.h>
#include <stdio.h>
#include "HelloWorld.h"   

JNIEXPORT void JNICALL   Java_HelloWorld_print(JNIEnv *env, jobject obj)  {
     printf("Hello World!\n");
     return;
}

L'implémentation de cette méthode native est simple. Il utilise la fonction printf pour afficher la chaîne " Hello World!"et puis revient. Comme mentionné précédemment, les deux arguments, le pointeur JNIEnv et la référence à l'objet sont ignorés.

Le programme C comprend trois fichiers d'en-tête:

jni.h -- Ce fichier d'en-tête fournit des informations dont le code natif a besoin pour appeler les fonctions JNI. Lors de l'écriture de méthodes natives, vous devez toujours incluez ce fichier dans vos fichiers source C ou C++. {[49] } The Le code l'extrait ci-dessus inclut également stdio.h car il utilise le printf fonction. {[15] } file Le fichier d'en-tête que vous avez généré en utilisant javah. Il il comprend le prototype C / C++ pour le Java_HelloWorld_print fonction. 2.6 Compiler la source C et créer une bibliothèque native

Rappelez-vous que lorsque vous avez créé la classe HelloWorld dans le HelloWorld.java fichier, vous avez inclus une ligne de code qui a chargé un natif bibliothèque dans le programme:

 System.loadLibrary("HelloWorld");   

Maintenant que tout le code C nécessaire est écrit, vous devez compiler {[57] } et construire ce natif bibliothèque.

Différents systèmes d'exploitation prennent en charge différentes façons de construire natif bibliothèque. Sur Solaris, la commande suivante crée une bibliothèque partagée appelé libHello-World.so:

 cc -G -I/java/include -I/java/include/solaris HelloWorld.c -o libHelloWorld.so

L'option-G demande au compilateur C de générer une bibliothèque partagée au lieu d'un Solaris normal fichier exécutable. En raison de la limitation de la largeur de page dans ce livre, nous divisons la ligne de commande en deux lignes. Vous devez taper la commande dans une seule ligne, ou placez la commande dans un fichier de script. Sur Win32, le la commande suivante construit une bibliothèque de liens dynamiques (DLL) HelloWorld.dll utilisation du compilateur Microsoft Visual C++:

 cl -Ic:\java\include -Ic:\java\include\win32 -MD -LD HelloWorld.c -FeHelloWorld.dll 

L'option -MD garantit que HelloWorld.dll est lié à la bibliothèque C multithread Win32. L'option -LD demande au compilateur C de générer une DLL au lieu d'une exécutable Win32 régulier. Bien sûr, sur Solaris et Win32 vous besoin de mettre dans les chemins d'inclusion qui reflètent la configuration sur votre propre machine.

2.7 Exécuter le Programme

À ce stade, vous avez les deux composants prêts à fonctionner programme. Le fichier de classe (HelloWorld.class) appelle une méthode native, et la bibliothèque native (Hello-World.dll) implémente la méthode native.

Parce que la classe HelloWorld contient sa propre méthode principale, vous pouvez exécuter le programme sur Solaris ou Win32 comme suit:

 java HelloWorld

, Vous devriez voir la sortie suivante:

   Hello World! 

Il est important de définir votre chemin de bibliothèque natif correctement pour que votre programme s'exécute. Le chemin de la bibliothèque native est une liste des répertoires que le Java virtuel recherches de la machine lors du chargement bibliothèques natives. Si vous n'avez pas de chemin de bibliothèque natif configuré correctement, alors vous voyez une erreur similaire à la suivante:

 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) 

Assurez-vous que la bibliothèque native réside dans l'un des répertoires de la bibliothèque native chemin. Si vous utilisez un système Solaris, le LD_LIBRARY_PATH la variable d'environnement est utilisée pour définir le chemin de la bibliothèque native. Faire assurez-vous qu'il comprend le nom du répertoire qui contient le libHelloWorld.so fichier. Si l' libHelloWorld.so fichier est dans le courant répertoire, vous pouvez émettre les deux commandes suivantes dans la norme shell (sh) ou KornShell (ksh) pour configurer le LD_LIBRARY_PATH variable d'environnement correctement:

 LD_LIBRARY_PATH=.
 export LD_LIBRARY_PATH

La commande équivalente dans le shell C (csh ou tcsh) est le suivant:

 setenv LD_LIBRARY_PATH .

Si vous utilisez un Windows 95 ou Windows NT machine, assurez-vous que HelloWorld.dll est dans le courant répertoire, ou dans un répertoire répertorié dans l'environnement PATH variable.

Dans Java 2 SDK 1.2 release, vous pouvez également spécifier la bibliothèque native chemin sur la ligne de commande java en tant que propriété système comme suit:

 java -Djava.library.path=. HelloWorld

L'option de ligne de commande" -D" définit une propriété système de plate-forme Java. Réglage du java.library.path la propriété ". " indique à la machine virtuelle Java de rechercher bibliothèques natives dans le répertoire courant.

 63
Author: Jonas, 2017-07-18 22:21:15

En termes simples, assurez-vous simplement de charger la bibliothèque pertinente qui contient la définition de la fonction, chargez la bibliothèque qui suit la spécification JNI et enveloppe la fonction cible de la première bibliothèque, exposez les méthodes natives de votre classe Java et vous devriez être prêt à partir.

Je recommanderais contre JNI brut car il contient beaucoup de code standard et vous finiriez par vous maudire si vous commencez à envelopper une bibliothèque big C. Par tous les moyens, n'hésitez pas à barboter en JNI au début, mais utilisez quelque chose comme JNA quand il s'agit de travail réel.

 11
Author: Sanjay T. Sharma, 2011-05-11 11:15:56

Vos options incluent:

Interface native Java
voir: https://en.wikipedia.org/wiki/Java_Native_Interface

Citation:

JNI permet aux programmeurs d'écrire des méthodes natives pour gérer les situations où une application ne peut pas être écrite entièrement dans le langage de programmation Java, par exemple lorsque la bibliothèque de classes Java standard ne prend pas en charge les fonctionnalités spécifiques à la plate-forme ou la bibliothèque de programmes

Natif Java Accès

Voir: https://en.wikipedia.org/wiki/Java_Native_Access

Citation:

Java Native Access est une bibliothèque développée par la communauté qui fournit aux programmes Java un accès facile aux bibliothèques partagées natives sans utiliser l'interface Java Native.

JNR-FFI

Voir: https://github.com/jnr/jnr-ffi

Citation:

Jnr-ffi est une bibliothèque java pour charger des bibliothèques natives sans écrire du code JNI à la main ou utiliser des outils tels que SWIG.

 4
Author: Dawnkeeper, 2015-01-15 10:42:05

Dans la catégorie "exotique", voir NestedVM, qui compile le C en Mips, et exécute un Mips VM à l'intérieur de la JVM.

Http://nestedvm.ibex.org/

 2
Author: ddyer, 2014-09-03 20:27:16

Checkout JNAerator. https://code.google.com/p/jnaerator/

Vous devez fournir le code source et les définitions du préprocesseur, etc.

 1
Author: Aykut Kllic, 2015-04-24 12:42:24

Si vous utilisez Windows et MinGW gcc, vous aurez peut-être besoin d'un indicateur supplémentaire si vous obtenez UnsatisfiedLinkError pour une méthode spécifique dans lib:

gcc -D_JNI_IMPLEMENTATION_ -Wl,--kill-at -I"%JAVA_HOME%"\include -I"%JAVA_HOME%"\include\win32 BestCode.c -shared -o BestCode.dll
 1
Author: Justas, 2016-06-09 08:12:56

JNI - Interface native Java

Pour appeler la fonction C à partir de Java, vous devez utiliser JNI

 0
Author: Steven Bialecki, 2013-03-22 20:37:57

Pour rendre la dll compatible 64 bits Supprimer l'option "- MD " de l'instruction ci-dessous

"cl -Ic:\java\include -Ic:\java\include\win32 -MD-LD HelloWorld.c-FeHelloWorld.dll "

 0
Author: Dila Gurung, 2015-05-18 06:51:00

J'ai une solution à ce problème. Ce que vous devez vous assurer, c'est que vous compilez le code à l'aide d'un compilateur c++ 64 bits pour appeler la fonction java s'exécutant sur JRE 64 bits. Parallèlement à cela, nous devons enregistrer le chemin du fichier dll créé dans "Chemin" sous "Variable d'environnement".

 0
Author: Dila Gurung, 2015-07-20 06:51:24

Assurez-vous d'abord de charger votre bibliothèque native ou .fichier dll dans le chemin de la classe en définissant le chemin à la propriété java.library.path

, Puis utilisez System.loadLibrary()

Do not use .dll extension at the end.
 0
Author: , 2017-09-07 14:19:45