Appelez un programme C depuis java avec JNA
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
|
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 |
Maintenant, la partie Java. Il faut avoir la lib JNA dans son classpath, bien évidement.
CHelloWorld.java
package io.warp10.ext.test; |
Test.java
public class Test { |
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 |
Et voilà.
Gestion mémoire avec try-with-resources
La version ci-dessus fonctionne, mais elle est fragile : si une exception survient, le finally gère le free. Avec JNA, on peut faire mieux en utilisant un AutoCloseable :
public class MonCString implements AutoCloseable { |
public class Test { |
Plus de finally explicite, plus de risque de fuite mémoire.
Structures C complexes avec com.sun.jna.Structure
JNA permet aussi de mapper des structures C complètes. Imaginons une fonction C qui renvoie une struct personne :
typedef struct { |
L’équivalent Java :
import com.sun.jna.Structure; |
Tableaux et callbacks
Passer des tableaux depuis Java vers C :
double somme_tableau(double* tab, int taille); |
double[] valeurs = {1.5, 2.5, 3.0}; |
Et les callbacks C depuis Java :
public interface CallbackC extends Callback { |
JNA vs JNI vs Panama FFI
| Critère | JNA | JNI | Panama FFI |
|---|---|---|---|
| Complexité | Aucune binding | Écrire du JNI C | Assez simple |
| Performance | Bonne (moyennant direct mapping) |
Excellente | Très bonne |
| Maintenance | Facile | Lourde | Facile |
| Infos de type | Réflexion | Header manuel | Descripteurs |
JNA est parfait pour du prototypage, de l’intégration rapide ou des appels ponctuels.
Project Panama (FFI moderne)
Depuis Java 22, le Foreign Function & Memory API (Panama) est proposé en standard (prévisualisation). C’est le successeur moderne de JNA/JNI, intégré directement dans le JDK :
import java.lang.foreign.*; |
Panama offre des performances proches de JNI sans le coût de maintenance. Pour les nouveaux projets, c’est la voie à privilégier - mais JNA reste très valable pour sa maturité et sa simplicité.