Exemple JNI (Java Native Interface)

Le code Java

Java Native Interface (JNI) est une technologie qui permet d'exécuter des fonctions C dans une classe Java.

package helloworld;

public class Greeter {

 static {
                //importation de la dll ou du fichier so
  System.loadLibrary("helloworld");
 }

 public static void main(String[] args) {
  Greeter greeter = new Greeter();
  greeter.sayHelloInNativeConsole();
  greeter.sayHelloInConsoleWithName("Ronan");
  
  //On récupère le resultat
  String message = greeter.formatHelloMessage("Ronan");
  System.out.println(message);
 }

 /**
  * Fonction native pour imprimer Hello ! dans la console native
  */
 private native void sayHelloInNativeConsole();
 
 /**
  * Fonction native pour imprimer Hello NOM ! dans la console native
  * 
  * @param name Le nom
  */
 private native void sayHelloInConsoleWithName(String name);
 
 /**
  * Fonction native pour formater le message
  * 
  * @param name Le nom
  * @return La chaine formatée
  */
 private native String formatHelloMessage(String name);

}

RĂ©sultat dans la console :

Hello !
Hello Ronan !
--- Hello Ronan ! ---

Le code C

Le fichier .h

Vous pouvez générer ce fichier à l'aide de la commande javah.

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class helloworld_Greeter */

#ifndef _Included_helloworld_Greeter
#define _Included_helloworld_Greeter
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     helloworld_Greeter
 * Method:    sayHelloInNativeConsole
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_helloworld_Greeter_sayHelloInNativeConsole
  (JNIEnv *, jobject);

/*
 * Class:     helloworld_Greeter
 * Method:    sayHelloInConsoleWithName
 * Signature: (Ljava/lang/String;)V
 */
JNIEXPORT void JNICALL Java_helloworld_Greeter_sayHelloInConsoleWithName
  (JNIEnv *, jobject, jstring);

/*
 * Class:     helloworld_Greeter
 * Method:    formatHelloMessage
 * Signature: (Ljava/lang/String;)Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_helloworld_Greeter_formatHelloMessage
  (JNIEnv *, jobject, jstring);

#ifdef __cplusplus
}
#endif
#endif

Le fichier .c

Ceci est l'implémentation du fichier .h

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

JNIEXPORT void JNICALL
Java_helloworld_Greeter_sayHelloInNativeConsole(JNIEnv *env, jobject obj) {
 printf("Hello World !\n");
 fflush(stdout); //flush pour avoir le print dans l'ordre dans Java
}

JNIEXPORT void JNICALL
Java_helloworld_Greeter_sayHelloInConsoleWithName(JNIEnv *env, jobject obj, jstring jstr) {
 //Conversion de jstring en pointer char
 const char *str = (*env)->GetStringUTFChars(env, jstr, 0);

 printf("%s %s %s", "Hello", str, "!\n");
 fflush(stdout); //flush pour avoir le print dans l'ordre dans Java

 //Nettoyage après l'utilisation de GetStringUTFChars
 (*env)->ReleaseStringUTFChars(env, jstr, str);
}

JNIEXPORT jstring JNICALL
Java_helloworld_Greeter_formatHelloMessage(JNIEnv *env, jobject obj,
  jstring jstr) {
 //Conversion de jstring en pointer char
 const char *name = (*env)->GetStringUTFChars(env, jstr, 0);
 char *str;

 //Formatage de la chaine
 sprintf(str, "%s %s %s %s", "--- Hello", name, "!", "---");

 //Nettoyage après l'utilisation de GetStringUTFChars
 (*env)->ReleaseStringUTFChars(env, jstr, name);

 jstring result = (*env)->NewStringUTF(env, str);
 return result;
}

Le fichier makefile

CLASS_PATH = ../bin

vpath %.class $(CLASS_PATH)

all : Greeter.h helloworld.o helloworld.dll

Greeter.h : $(CLASS_PATH)/helloworld/Greeter.class
 javah -classpath $(CLASS_PATH) helloworld.Greeter

helloworld.o : helloworld.c helloworld_Greeter.h
 gcc -I"C:\Program Files\Java\jdk1.8.0_211\include" -I"C:\Program Files\Java\jdk1.8.0_211\include\win32" -c $< -o $@

helloworld.dll : helloworld.o
 gcc -Wl,--add-stdcall-alias -shared -o $@ $<
 
clean :
 rm helloworld_Greeter.h helloworld.o helloworld.dll

Avec Eclipse

Convertir un projet Java en projet C/C++

Clic-droit sur le projet > New > Other...

Dans C/C++, SĂ©lectionnez Convert to a C/C++ Project (Adds C/C++ Nature)

Onglet Build targets

Il faut changer de perspective pour voir cet onglet. Window > Perspective > Open perspective > Other... > C/C++

Cet Onglet est généralement sur la partie droite d'Eclipse.

Si vous ne voyez pas cet onglet vous pouvez cliquer sur le menu Window > Show view > Build Targets

Commentaires