IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Entrée/Sortie Java Discussion :

[JNI] Appel DLL externe C# en Java


Sujet :

Entrée/Sortie Java

  1. #1
    Membre averti Avatar de Contrec
    Homme Profil pro
    Inscrit en
    Mars 2005
    Messages
    597
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38

    Informations forums :
    Inscription : Mars 2005
    Messages : 597
    Points : 342
    Points
    342
    Par défaut [JNI] Appel DLL externe C# en Java
    Bonjour à tous,

    Je rencontre actuellement des difficultés pour appeler des fonctions d'une dll C# à partir de Java en utilisant JNI.

    J'ai tenté de suivre le tutoriel suivant :

    http://www.codeproject.com/Articles/...a-Java-program

    J'arrive à faire fonctionner le tutoriel qui utiliser le système Java --> C++ --> C# pour lier les 2 mondes entre eux.

    Mais ma problématique est différente car moi j'ai besoin d'appeler du C# compilé dans une dll externe et non un .netmodule comme dans le tuto ci-dessus.

    En gros j'ai pensé encapsuler ma dll externe C# dans un autre projet C# qui lui serait compilé en .netmodule et appelé par le Java via du C# managé.

    Le schéma serait : Java --> C++ --> C# .netmodule --> C# dll externe.

    J'ai donc crée le code source pour tout cela :

    Code java (CallISyncJava.java) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    public class CallISyncJava { 
     
        static {
            System.load("C:\\Users\\Administrateur\\Documents\\JNI\\POC\\CallISyncCpp.dll");
        }
     
        public native void DisplayText();
     
        public static void main (String[] args) {
            CallISyncJava ISyncInstance = new CallISyncJava();
            ISyncInstance.DisplayText();
        }
    }
    Code Java JNI .h auto généré dans un dossier "Java" (CallISyncJava.h) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    /* DO NOT EDIT THIS FILE - it is machine generated */
    #include <jni.h>
    /* Header for class CallISyncJava */
     
    #ifndef _Included_CallISyncJava
    #define _Included_CallISyncJava
    #ifdef __cplusplus
    extern "C" {
    #endif
    /*
     * Class:     CallISyncJava
     * Method:    DisplayText
     * Signature: ()V
     */
    JNIEXPORT void JNICALL Java_CallISyncJava_DisplayText
      (JNIEnv *, jobject);
     
    #ifdef __cplusplus
    }
    #endif
    #endif
    Code C++ (CallISyncCpp.cpp) :

    #include <jni.h>
    #include "..\MCPP\CallISyncJava.h"
    #include "..\Java\CallISyncJava.h"


    JNIEXPORT void JNICALL Java_CallISyncJava_DisplayText(JNIEnv *jn, jobject jobj)
    {
    ISyncWrapperCpp *myISyncInstance = new ISyncWrapperCpp();
    myISyncInstance->callDisplayText();
    }

    Code C++ .h placé dans un dossier MCPP qui appelle le C# .netmodule (CallISyncJava.h):

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    #using <mscorlib.dll>
    #using "..\ISyncWrapper\bin\Debug\ISyncWrapper.netmodule"
     
    using namespace System;
     
    public __gc class ISyncWrapperCpp
    {
        public:
            ISyncWrapper __gc *t;
            ISyncWrapperCpp() {
                t = new ISyncWrapper();
            }
     
            void callDisplayText() {
                t->DisplayText();
            }
    };
    Code C# compilé en .netmodule (ISyncWrapper.cs) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
     
     
    public class ISyncWrapper
    {
        ISync.ISync myISyncRef = new ISync.ISync();
     
        /**
         * Default constructor.
         */
        public ISyncWrapper() { }
     
        /*
         * Test displaying some text without parameters in the console.
         */
        public void DisplayText()
        {
            this.myISyncRef.DisplayText();
        }
    }
    Le code C# ISyncWrapper.cs embarque une référence externe vers une dll ISync.dll dont je ne connais que la signature de méthode DisplayText(). Pour information cette méthode n'est qu'un exemple simple pour afficher un texte, en réalité cette dll sera plus complexe, là j'en ai crée une de test juste pour moi avec une seule méthode DisplayText() qui affiche une popup C#.

    Donc après compilation des différents fichiers source, quand j'exécute, la JVM crashe :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    #
    # A fatal error has been detected by the Java Runtime Environment:
    #
    #  Internal Error (0xe0434352), pid=1144, tid=4424
    #
    # JRE version: 7.0_17-b02
    # Java VM: Java HotSpot(TM) Client VM (23.7-b01 mixed mode, sharing windows-x86 )
    # Problematic frame:
    # C  [KERNELBASE.dll+0x812f]  RaiseException+0x54
    #
    # Failed to write core dump. Minidumps are not enabled by default on client versions of Windows
    #
    # An error report file with more information is saved as:
    # C:\Users\Administrateur\Documents\JNI\POC\hs_err_pid1144.log
    #
    # If you would like to submit a bug report, please visit:
    #   http://bugreport.sun.com/bugreport/crash.jsp
    # The crash happened outside the Java Virtual Machine in native code.
    # See problematic frame for where to report the bug.
    #
    Le fichier de crash généré par la JVM est en fichier attaché.



    Si quelqu'un peut m'aider à réaliser cela, peut-être que je n'utilise pas la bonne méthode et qu'il y a une façon plus simple d'appeler une dll externe à partir de Java en ne connaissant que la signature des méthodes.

    Merci d'avance, n'hésitez pas à me demander des détails car là je suis totalement bloqué depuis plusieurs jours.
    Contrec
    Fichiers attachés Fichiers attachés

  2. #2
    Membre chevronné
    Inscrit en
    Mai 2006
    Messages
    1 364
    Détails du profil
    Informations forums :
    Inscription : Mai 2006
    Messages : 1 364
    Points : 1 984
    Points
    1 984
    Par défaut
    Deja, quand on utilise JNI, lors du loadLibrary, il ne faut pas préciser l'extension (sous linux, il prendra un .so et sous windows un .dll). Ensuite, je n'ai jamais essayé d'utiliser un chemin complet mais il faudrait essayer de mettre le .dll dans le repertoire d'execution et de remplacer
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    System.load("C:\\Users\\Administrateur\\Documents\\JNI\\POC\\CallISyncCpp.dll");
    par
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    System.load("CallISyncCpp");
    Si ca marche, c'est bien. Sinon, a ta place, pour savoir d'ou vient l'erreur, je créerais un executable c++ qui appelle le code c#. Comme ca, ca permettrait de savoir si le probleme se situe au niveau java->c++ ou bien c++->c#.

  3. #3
    Membre averti Avatar de Contrec
    Homme Profil pro
    Inscrit en
    Mars 2005
    Messages
    597
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38

    Informations forums :
    Inscription : Mars 2005
    Messages : 597
    Points : 342
    Points
    342
    Par défaut
    Merci pour ta réponse, j'ai testé tes changements au niveau du path et du coup il ne trouve plus la dll :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    Exception in thread "main" java.lang.UnsatisfiedLinkError: Expecting an absolute path of the library: CallISyncCpp
            at java.lang.Runtime.load0(Unknown Source)
            at java.lang.System.load(Unknown Source)
            at CallISyncJava.<clinit>(CallISyncJava.java:4)
    Et pour ce qui est du code de test, j'ai fait un projet de test en C# pour valider le .netmodule (CallISyncJava.h) et tout est ok.

    Dois-je quand même le valider en C++ d'après toi ?

  4. #4
    Membre chevronné
    Inscrit en
    Mai 2006
    Messages
    1 364
    Détails du profil
    Informations forums :
    Inscription : Mai 2006
    Messages : 1 364
    Points : 1 984
    Points
    1 984
    Par défaut
    Citation Envoyé par Contrec Voir le message
    Merci pour ta réponse, j'ai testé tes changements au niveau du path et du coup il ne trouve plus la dll
    Oui, effectivement, je n'avais pas vu que tu faisais un System.load. Je n'ai jamais essayé de charger une dll avec parce qu'il est toujours mieux d'utiliser un System.loadLibrary qui est portable. Essaie peute etre avec celui-ci, on ne sait jamais.

    Citation Envoyé par Contrec Voir le message
    Dois-je quand même le valider en C++ d'après toi ?
    Sans aucun doute, oui Parce que lorsque cela sera validé, tu seras sur que le probleme vient de l'appel java -> c++. Tant que ce n'est pas le cas, on peut supposer que le probleme vient de c++ -> c#

    Concernant la compilation du code c++, tu as utilisé quels flags (en particulier pour le link) ? Ca vaudrait peut etre le coup de faire une fonction simple pour vérifier si tu arrives à appeler ton code natif à partir de java. Un truc du genre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    JNIEXPORT jint JNICALL Java_CallISyncJava_test
      (JNIEnv *env, jobject o)
    {
       return 5;
    }
    Et voir si apres appel, tu recuperes bien 5.

  5. #5
    Membre averti Avatar de Contrec
    Homme Profil pro
    Inscrit en
    Mars 2005
    Messages
    597
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38

    Informations forums :
    Inscription : Mars 2005
    Messages : 597
    Points : 342
    Points
    342
    Par défaut
    J'ai essayé avec
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    System.loadLibrary("CallISyncCpp");
    qui ne prends que le nom de la dll en paramètre et je retrouve la toute première erreur de JVM;

    Je vais essayer de tester le tout en C++ comme tu dis et je reviens poster mes résultats.

    Merci

    Edit : Pour générer la dll C++ sous Visual Studio Epress 2010, j'ai utilisé le flag /clr:oldSyntax sinon j'avais des erreurs.

  6. #6
    Membre chevronné
    Inscrit en
    Mai 2006
    Messages
    1 364
    Détails du profil
    Informations forums :
    Inscription : Mai 2006
    Messages : 1 364
    Points : 1 984
    Points
    1 984
    Par défaut
    Citation Envoyé par Contrec Voir le message
    Edit : Pour générer la dll C++ sous Visual Studio Epress 2010, j'ai utilisé le flag /clr:oldSyntax sinon j'avais des erreurs.
    Il faudrait poster la commande utilisée lors du link complete. De mémoire, j'avais eu une erreur qui ressemble à ce que tu as quand je n'avais pas mis l'option shared lors du link.

  7. #7
    Membre averti Avatar de Contrec
    Homme Profil pro
    Inscrit en
    Mars 2005
    Messages
    597
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38

    Informations forums :
    Inscription : Mars 2005
    Messages : 597
    Points : 342
    Points
    342
    Par défaut
    Euh je fais comment pour récupérer cette commande à partir de VS Express ? J'ai regardé dans les fichiers de log générés lors de la compilation du projet et j'ai pas trouvé, ou mal regardé...

  8. #8
    Membre chevronné
    Inscrit en
    Mai 2006
    Messages
    1 364
    Détails du profil
    Informations forums :
    Inscription : Mai 2006
    Messages : 1 364
    Points : 1 984
    Points
    1 984
    Par défaut
    En ce qui me concerne, j'utilise Eclipse. Et la ligne de commande apparait dans la console. Pour VS Express, je ne sais pas. A la limite, peux tu regarder les option de link et verifier que la librairie est bien "shared" (peut etre une case à cocher ou un truc du genre) ?

  9. #9
    Membre averti Avatar de Contrec
    Homme Profil pro
    Inscrit en
    Mars 2005
    Messages
    597
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38

    Informations forums :
    Inscription : Mars 2005
    Messages : 597
    Points : 342
    Points
    342
    Par défaut
    J'ai récupéré la liste des options de compilation du projet dans Visual Studio :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    /GS /analyze- /W3 /Zc:wchar_t /I"C:\Program Files\Java\jdk1.7.0_17\include" /I"C:\Program Files\Java\jdk1.7.0_17\include\win32" /Zi /Od /Fd"Debug\vc110.pdb" /fp:precise /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_USRDLL" /D "CALLISYNCCPP_EXPORTS" /D "_WINDLL" /D "_UNICODE" /D "UNICODE" /errorReport:prompt /WX- /Zc:forScope /Oy- /clr:oldSyntax /FU"C:\Program Files\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\mscorlib.dll" /MDd /Fa"Debug\" /EHa /nologo /Fo"Debug\" /Fp"Debug\CallISyncCpp.pch" /AI"C:\Users\Administrateur\Documents\JNI\POC\MCPP"
    Je n'ai pas vu l'option Shared. Je continue de rechercher et de faire un test en C++ pour voir si le soucis vient du côté C++ ou Java.

  10. #10
    Membre averti Avatar de Contrec
    Homme Profil pro
    Inscrit en
    Mars 2005
    Messages
    597
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38

    Informations forums :
    Inscription : Mars 2005
    Messages : 597
    Points : 342
    Points
    342
    Par défaut
    De plus j'ai rajouté la fonction test() pour voir si le soucis était un appel à JNI et cela fonctionne bien :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    > java CallISyncJava
    > 5
    Il faut donc que je crée un projet de test C++ qui appelle le C# (et aussi que je vois pour l'option Shared). Je vous tient au courant.

    Contrec

Discussions similaires

  1. Problème avec un appel DLL externe
    Par popeyes dans le forum Langage
    Réponses: 8
    Dernier message: 26/03/2015, 12h07
  2. [WD15] Appel DLL externe (typage paramètres à passer)
    Par Tagada69 dans le forum WinDev
    Réponses: 11
    Dernier message: 22/10/2010, 09h26
  3. [JNI] Appeler une DLL Fortran à partir de Java
    Par Graffity dans le forum Entrée/Sortie
    Réponses: 2
    Dernier message: 13/11/2008, 00h07
  4. [JNI]appel d'un dll en Java
    Par Aida dans le forum Entrée/Sortie
    Réponses: 22
    Dernier message: 23/01/2008, 16h19
  5. Appel aux fonctions d'une DLL externe ??
    Par Fbartolo dans le forum Access
    Réponses: 7
    Dernier message: 21/11/2005, 17h54

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo