Et oui, on peut appeler nativement une lib C, C++ Rust ou Go directement en Java grâce à JNA.
En fait c’est facile.
D’abord, il faut une lib en C. Par exemple en voici une :
helloworld.
h
char *hello(char* ch);
helloworld.
c
#include "helloworld.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
char* hello(char* ch) {
char prefix[] = "Hello ";
char *res;
res = malloc(strlen(prefix) + strlen(ch));
strcpy(res, prefix);
strcat(res,ch);
return res;
}
Hey, mais, il y a un malloc
sans free
, ça craint. Bon, pas de soucis, on verra plus loi comment faire un free
après l’appel.
Ok, maintenant, on compile :
$ gcc -c helloworld.c
$ gcc -shared -dynamiclib helloworld.o -o ./helloworld.so
Maintenant, la partie Java. Il faut avoir la lib JNA dans son classpath, bien évidement.
CHelloWorld.java
package io.warp10.ext.test;
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
public interface CHelloWorld extends Library {
// On charge la lib
CHelloWorld INSTANCE = Native.load("helloworld.so", CHelloWorld.class);
// on décrit l'interface utilisée
Pointer hello(String g);
// Youpi, on pourra appeler free
void free(Pointer p); // JNA le fournit (et pas que ça)
}
Test.java
public class Test {
public static void main(String[] args) {
Pointer ptr = null;
try {
// on appelle notre fonction C
ptr = CHelloWorld.INSTANCE.hello(args[0]);
// on parse le résultat
System.out.println(ptr.getString(0));
} catch (Exception e) {
throw e;
} finally {
// On libère la mémoire
if (null != ptr) {
CHelloWorld.INSTANCE.free(ptr);
}
}
}
}
On compile :
$ javac -cp ./jna-5.10.0.jar ./*.java
On exécute :
$ java -cp /opt/jna-5.10.0.jar:./* mon.package.Test Kitty
Hello Kitty
Et voilà.