58 votes

Accéder à une bibliothèque partagée C++ depuis Java : JNI, JNA, CNI, ou SWIG ?

Quelle méthode suivante (ou autre) recommanderiez-vous pour accéder à une bibliothèque partagée C++ depuis Java et pourquoi?

  1. JNI: J'ai entendu dire que cela comporte un certain nombre de pièges et est plutôt difficile à entreprendre?
  2. SWIG: Apparemment, cela rend l'utilisation de JNI plus facile, mais j'ai entendu dire que cela pose également des problèmes?
  3. JNA: Je pourrais écrire une interface C et l'utiliser avec JNA à la place, ce qui est apparemment beaucoup plus facile que JNI?
  4. CNI: Apparemment, cela est plus facile que JNI?
  5. Une autre bibliothèque: elle ne peut pas être commerciale et je préférerais quelque chose qui soit toujours bien maintenu (cela exclurait JNIEasy, JNative et JACE, je crois).

J'essaie de minimiser le temps de développement et les problèmes à l'avenir. Toute information sur les avantages/inconvénients de chacune de ces méthodes serait appréciée.

MODIFICATION : Idéalement, je pourrais utiliser mes objets C++ en Java, mais comme je l'ai mentionné au #3, je pourrais écrire une interface C en utilisant uniquement des fonctions si nécessaire. L'interface C++ que je voudrais avoir disponible en Java ressemble à ceci :

class MyObj1
{
    MyObj1(std::string, bool);
    bool Func1();
    void Func2(bool);
}

class MyObj2
{
    MyObj2(MyObj1*);
    ssize_t Func(uint8_t *, size_t, MyObj1);
}

L'interface réelle est un peu plus compliquée, mais cela illustre le type d'objets et de méthodes que j'utiliserai. Certains des objets sont dérivés, mais l'interface Java n'a pas besoin d'avoir de comportement polymorphe.

57voto

Andy Thomas Points 30979

Pour Java->C++, j'ai utilisé JNI, JNA et joué avec SWIG.

JNA est le plus facile à utiliser, mais comme vous le notez, nécessite d'écrire à la main une interface C pour l'API C++. Il peut également être plus lent que JNI d'un ordre de grandeur. Cependant, j'ai mesuré des appels individuels à quelques centaines de nanosecondes sur une machine, donc cela ne devrait pas poser de problème sauf dans un goulot d'étranglement.

JNA spécifie redondamment les signatures de fonctions C, en Java. JNI peut spécifier redondamment les signatures de fonctions Java, dans des chaînes C. Des divergences dans l'une ou l'autre peuvent entraîner un comportement inattendu à l'exécution.

Personnellement, j'utiliserais JNA à moins que l'interface ne soit suffisamment complexe pour rendre fastidieuse l'écriture manuelle de l'interface C pour vous, ou que les appels individuels prennent plus de quelques centaines de nanosecondes.

Cette semaine, j'ai été confronté à une telle exception - une interface C++ riche avec de nombreuses classes et méthodes. J'ai commencé à jouer avec SWIG, et ça a l'air prometteur. Cela a été assez facile à utiliser et génère automatiquement les liaisons Java et l'implémentation C. Les pointeurs intelligents ont nécessité un peu de travail supplémentaire - il faut instruire SWIG pour instancier les modèles.

MODIFICATION (un an plus tard):

SWIG est étonnamment puissant. Il peut également être plus complexe à mettre en place. Pour des interfaces simples et minces, je considérerais probablement d'abord JNA ou JNI. Mais SWIG est pratique pour des interfaces épaisses.

Je suis un peu surpris que SWIG fonctionne, compte tenu de la complexité de certains fichiers d'en-tête C++. Mais SWIG semble ne pas avoir de difficulté.

J'ai dû écrire quelques typemaps SWIG et des macros contenant du code C++/JNI. Par exemple, passer des std::strings par référence nécessitait un typemap personnalisé. Transformer les exceptions C++ en exceptions Java lancées nécessitait un typemap et une macro.

Aucun changement n'était nécessaire à nos fichiers d'en-tête sauf que SWIG instancie pleinement un template de pointeur intelligent, qui avait été paramétré avec certaines classes ne satisfaisant pas son attente d'un constructeur par défaut. Solution : ajouter quelques constructeurs par défaut.

9voto

zOlive Points 1011

Une autre nouvelle alternative est BridJ, qui est bien soutenue par JNAerator et est jeune mais déjà puissante (déni : je suis l'auteur :-)).

Ça fonctionne comme JNA mais supporte également les classes C++ et les conventions d'appel (y compris les méthodes virtuelles...), donc vous n'avez pas besoin d'écrire une interface C intermédiaire.

4voto

none Points 41

Essayez d'utiliser http://jnaerator.googlecode.com/ Il générera automatiquement du code à partir de vos fichiers d'en-tête

4voto

fco.javier.sanz Points 1582

J'ai récemment évalué javacpp. Je suis assez satisfait de ces évaluations et il fonctionne sur Android, ce qui était une exigence pour moi.

0voto

twid Points 11

J'ai utilisé swig, je trouve que cela a vraiment réduit le type de développement... aussi facile de créer des objets..

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X