Interfacer du Java avec du C (JDK 1.1) |
L'interet d'un tel interfacage apparait si l'on dispose d'un code natif tres performant ou trop gros pour que tout soit recrit. L'exemple ci-dessous montre comment envoyer des ordres UNIX en passant par la commande system du C.
Le principe est d'ecrire un fichier qui contient un main appelant une
classe dont l'implementation est en C.
Un fichier distinct du main (mais pas necessairement) va decrire cette classe (appelee sur la figure Toto et dans l'exemple ci-dessous Interface2) qui inclut les fonctions ou procedures C . Dans cette classe, on declarera le profil des fonctions C avec un status native. Puis on chargera la librairie dans un bloc static qui n'est pas une methode. |
![]() |
|
Programme (2 fichiers differents) :
// fichier system2.java
public class system2 {
public static void main(String args[]) {
unix.hello() ; System.out.println("Je demande un <ls>.") ; unix.ls() ; System.out.println("Je demande un <pwd>.") ; unix.pwd(); System.out.println("Une commande plus complexe.") ; unix.passe_parametre() ; // methode java qui va appeler du C
// fichier Interface.java class Interface2 {
public native void hello() ; public native void ls() ; public native void pwd() ; public native void passe_param(String java_string, int entier, float flottant, char caractere) ;
{
System.loadLibrary("ma_lib") ; // variables utilisees pour l'echange java/c public String java_string ; public int entier ; public float flottant ; public char caractere ; public void passe_parametre() {
entier = 10 ; flottant = (float) 3.14159 ; caractere = 'q' ; passe_param (java_string, entier, flottant, caractere) ; // fonction C |
javac Interface2.java javah -jni Interface2 |
/* Fichier Interface2Imp.c dont la compilation va
donner un fichier appele libma_lib.so */
#include <jni.h> #include <stdio.h> #include "Interface2.h" /* voir le fichier Interface.h pour le profile des fonctions C a ecrire */ JNIEXPORT void JNICALL Interface2_hello(JNIEnv *env, jobject obj) {
JNIEXPORT void JNICALL Interface2_ls(JNIEnv *env, jobject obj) {
JNIEXPORT void JNICALL Interface2_pwd(JNIEnv *env, jobject obj) {
JNIEXPORT void JNICALL void Interface2_passe_1param(JNIEnv *env, jobject obj, jstring j_chne, jint j_entier, jfloat j_reel, jchar j_car) {
fprintf(stdout,"$s $d $f $c\n",c_chne, j_entier, j_reel, j_car); (*env)->ReleaseStringUTFChars(env, j_chne, c_chne); return ; // NB : j'aimerai bien savoir pourquoi javah m'oblige a appeler ma fonction Interface2_passe_1param au lieu de Interface2_passe_param ! |
On dispose maintenant de deux fichiers .c qu'il faut compiler et mettre dans une librairie qui s'appelera ici libma_lib.so (soit sous Solaris) :
|
|
|
|
Interface2.java Interface2Imp.c |
Interface2.class Interface2.h |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
De meme, les objets JAVA sont designes en C par :
|
|
|
|
|
|
L'operation inverse est egalement possible :
|
|
|
|
|
|
Le profile des parametres suit la syntaxe suivante :
Exemple type d'une procedure C utilisant une methode d'un objet JAVA :
JNIEXPORT void JNICALL
Java_Callbacks_nativeMethod(JNIEnv *env, jobjectobj,
jint parametre)
{
jmethodID methode = (*env)->GetMethodID(env, obj_a_appeler, "methode_a_appeler", "(I)V"); (*env)->CallVoidMethod(env, obj, methode, parametre); |
La JNI offre un reel progres par rapport a la version 1.0 du JKD et permet d'interfacer proprement et relativement facilement JAVA avec C (C++ est bien sur egalement supporte).