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

C++ Discussion :

DLL pour VBA 32bits à DLL pour JAVA 64bits


Sujet :

C++

  1. #1
    Nouveau Candidat au Club
    Homme Profil pro
    Développeur COBOL
    Inscrit en
    Février 2017
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur COBOL
    Secteur : Finance

    Informations forums :
    Inscription : Février 2017
    Messages : 6
    Points : 0
    Points
    0
    Par défaut DLL pour VBA 32bits à DLL pour JAVA 64bits
    Bonjour à la communauté.

    Suite à de nombreuses recherches infructueuses, je me suis obligé à poster mon problème. C’est la première fois que je fais appel à vous, car je ne trouve aucune solution...

    Je vais essayer de présenter mon projet le plus simplement possible...

    J’ai créé un code JAVA basé sur un modèle mathématique (méthode de koutrouvelis) permettant d’estimer les paramètres d’une loi alpha stable.
    La méthode que j’ai ainsi codée fait appel à des fonctions provenant d’une DLL.

    Cette DLL, codée en c++, était initialement utilisée pour un projet similaire, mais codé sous Excel/VBA. (Déjà je ne sais pas si cela à une quelconque importance dans l’appel des fonctions... ?)

    PS : Je ne connais strictement rien à c++ ni aux DLL.

    Mon environnement de travail :
    - Windows 10 pro
    - 64bits
    - Logiciel utilisé : Netbeans
    - Compileur : JAVA SE/jdk 1.8
    - Librairie particulière utilisées : JNative / ssj-2.5
    - La DLL est placée dans le system32 de Windows

    Et voici les erreurs donner en retour de java :

    run:
    java.lang.UnsatisfiedLinkError: C:\Windows\System32\Stable.dll: Can't load IA 32-bit .dll on a AMD 64-bit platform
    at java.lang.ClassLoader$NativeLibrary.load(Native Method)
    at java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1929)
    at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1847)
    at java.lang.Runtime.loadLibrary0(Runtime.java:870)
    at java.lang.System.loadLibrary(System.java:1119)
    at launcher.Runner.<clinit>(Runner.java:30)
    Exception in thread "main" Java Result: 1
    BUILD SUCCESSFUL (total time: 0 seconds)
    Le retour montre clairement que l’erreur provient de l’incapacité à lire la DLL car c’est une 32bits et mon système est en 64.

    Or j’ai cherché à recompiler cette DLL en c++, mais rien à faire ! cela ne fonctionne pas. (Même avec des forums dédiés aux DLL, mes connaissances en c++ ne le permettent simplement pas…)

    Une âme charitable pourrait-elle me conseiller ? me proposer une solution de compilation en 64bits pour cette DLL ? Une autre approche ? Des remarques ?

    Merci à tous !

  2. #2
    Expert éminent sénior
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2005
    Messages
    5 073
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2005
    Messages : 5 073
    Points : 12 119
    Points
    12 119
    Par défaut
    Le texte d'explication ne semble pas vraiment correspondre aux sources (mention de .xla inexistant, etc...).
    Peut-être des modifications dans la source qui n'ont pas été répercutées dans la présentation.

    Il s'agit d'une "simple" Dll codée en C++, exportant une API C.
    C'est la combinaison/configuration la plus courante des Dll.
    Le VB (.bas) n'est qu'un simple wrapper autour de cette Dll exportant une API C.

    Effectivement, charger un code binaire 32bits dans un processus 64bits, ça le fait pas trop.

    Mais, sauf erreur de ma part, il est tout à fait possible d'avoir un JRE 32bits sur un OS 64bits.

    Donc, charger cette Dll dans un JRE 32bits ne devrait pas poser de problème.


    Recompiler le code pour du 64bits est une option. Mais il faut vérifier que ce code soit "64bits aware", et au vue du code quelque peu archaïque, c'est loin d'être évidant.

    Le code source contient des indices sur le fait qu'il a été conçu pour être compilable qu'avec VC++.
    Mais le fichier projet ou le fichier solution de Visual Studio n'a pas été fourni.

    Il vous faudra donc, soit adapter le code source à votre IDE C++, soit utiliser Visual Studio en créant un projet type Dll et entièrement le configurer pour faire le travail.
    Pour l'option Visual Studio, c'est pas très complexe mais cela ne s'improvise pas.
    Regardez un tutoriel sur comment faire une Dll en C++ avec Visual Studio exportant un API C.
    C'est pas compliqué mais faut avoir quelques notions en C et en C++.

    P.S.:
    - La DLL est placée dans le system32 de Windows
    Ce n'est pas bien, "system32" n'est pas un dépotoir.
    https://www.chilkatsoft.com/java-loa...ry-windows.asp

  3. #3
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Le code est primitif et ressemble plus à du C qu'à du C++ dans pas mal de cas, mais ne semble pas avoir de conversions entre pointeurs et types entiers, donc il devrait continuer à marcher tant que la taille des tableaux utilisés tient dans un int 32 bits.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  4. #4
    Nouveau Candidat au Club
    Homme Profil pro
    Développeur COBOL
    Inscrit en
    Février 2017
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur COBOL
    Secteur : Finance

    Informations forums :
    Inscription : Février 2017
    Messages : 6
    Points : 0
    Points
    0
    Par défaut
    Merci pour vos réponses qui m'aide déjà à bien comprendre le fonctionnement.

    J'ai effectivement vite compris que la compatibilité était le réel problème.
    Comme j'aimerais savoir si mon code fonctionne je passe pour le moment l'étape de la recompilation de la librairie.
    Bizarrement je n'avais pas du tout pensais à lancer mon code avec une JRE 32bit.. ça semble pourtant évident.

    Bacelar :
    Donc, charger cette Dll dans un JRE 32bits ne devrait pas poser de problème.
    J'ai donc suivi ton conseil est j'ai installer le jdk1.8.0_121 (version 32bit de java).
    Netbeans semble vouloir lancer mon code sur la Plateforme 32bit et mon programme réussi bien a ouvrir le contenue de la DLL.
    C'est donc un grand pas en avant!

    En revanche une autre erreur survient lors de l'appel de la première fonction:

    Erreur:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    Exception in thread "main" java.lang.UnsatisfiedLinkError: launcher.Runner.al(JD)D
    	at launcher.Runner.al(Native Method)
    	at launcher.Runner.Alph(Runner.java:116)
    	at launcher.launcher.main(launcher.java:21)
    C:\Users\Laurent\AppData\Local\NetBeans\Cache\8.2\executor-snippets\run.xml:53: Java returned: 1
    BUILD FAILED (total time: 2 seconds)
    D’après ce que j'ai lu sur pas mal de forum, cela pourrait provenir d'une mauvaise définition de la fonction dans la DLL, mais comme vous l'avez tous deux mentionné, VBA comme mon code java ne sont que des wrapper.. cela ne devrais donc pas provenir de là?!

    Une autre possibilité et que je fait mal appel à mes fonctions ou à ma dll.. et j'avoue que cette partie reste flou car la DLL s'ouvre!?

    Voici mon procédé:
    La class ou je défini les fonctions de la librairie:
    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
    25
    26
     
    public class Runner {
     
        public static native double al(long a, double b);
        ...
        ...
     
     
     
        static {
            System.loadLibrary("Stable");
        }
     
       ...
       ... 
     
       public double Alph(double[] x){
           double Var = 0;
           double[] Tab1 = null;
           Tab1 = new double[x.length-1];
           for(int i = 0; i <x.length-1; i++){
               Tab1[i] = x[i+1];            
           } 
           Var = al(x.length,Tab1[0]);    //appel de la fonction (erreur sur l'appel)
           return Var;
        }
    Cela semble t'il correct?


    Ce n'est pas bien, "system32" n'est pas un dépotoir.
    C'est noté. J'ai placé la DLL dans le bin du jre comme mentionné dans le tuto.


    Médinoc:
    il devrait continuer à marcher tant que la taille des tableaux utilisés tient dans un int 32 bits.
    J'utilise un échantillon de données de 30 valeurs. La taille du tableau est donc faible pour le moment..

    Merci pour votre aide.

  5. #5
    Expert éminent sénior
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2005
    Messages
    5 073
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2005
    Messages : 5 073
    Points : 12 119
    Points
    12 119
    Par défaut
    Là, c'est un peu le brouillard.
    JNI, c'est très très loin pour moi.

    Je pense qu'on pourra commencer une stratégie de wrapping pour bien vérifier le pont entre la Dll C et JNI.

    La stratégie consiste à faire une simple Dll en utilisant juste les exemples comme :
    http://jmdoudoux.developpez.com/cour...ap-jni.php#jni

    Une fois cette Dll créée et utilisée, vous changez le code de cette Dll pour qu'elle appelle la Dll C initiale.

    J'ai des appréhensions sur des problématiques de convention d'appel entre la Dll C et ce qu'attend JNI (qui était, dans mes souvenirs, très psychorigide).

  6. #6
    Nouveau Candidat au Club
    Homme Profil pro
    Développeur COBOL
    Inscrit en
    Février 2017
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur COBOL
    Secteur : Finance

    Informations forums :
    Inscription : Février 2017
    Messages : 6
    Points : 0
    Points
    0
    Par défaut
    J'ai suivi votre tuto pour le wrapper.
    - Création du fichier header en .h avec l'invite de commande et les differents PATH etc..

    La ou ça pause problème et lors de la création du fichier .c. Je suis partie du principe qu'il fallait recompiler la totalité du code C provenant de Code-Source.com .
    J'ai donc ajouté tous les fichiers d’en tête et mon header créer initialement à un projet C/C++ pour DLL sur netbeans.
    J'ai ajouté les différents path pour les 'includes' (MinGw et le jdk).
    Le problème est que l'IDE me montre des erreurs. (cf. fichier pdf en pièce-jointe)
    - il ne veut pas prendre en compte le point virgule, le ":" après public ou encore ne veux pas définir la variable Lserie..
    et cela dans plusieurs fichiers .h

    messages d'erreur:

    Unexpected token: :

    Unexpected token: ;

    Unable to resolve identifier Lserie.

    Déjà est-ce bien la bonne méthode que j'utilise pour le JNI, à savoir, faut-il recompiler le code source en totalité ?

    Merci.
    Images attachées Images attachées

  7. #7
    Expert éminent sénior
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2005
    Messages
    5 073
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2005
    Messages : 5 073
    Points : 12 119
    Points
    12 119
    Par défaut
    Je suis partie du principe qu'il fallait recompiler la totalité du code C provenant de Code-Source.com .
    Non, cela n'est pas forcément nécessaire.
    Cela serait nécessaire si votre wrapper utilise une C-Runtime différente de le Dll fournie et que l'isolation mémoire entre le client de la Dll et la Dll n'est pas garantie par l'API.
    J'arrive plus à voir où est l'URL vers le projet dans "Code-Source.com".

    Commencez par pouvoir utiliser JNI sans problème, cf. mon précédent post.

    Une fois la Dll "Hello Word" opérationnelle, vous commencez à utiliser les API de la "vraie" Dll dans cette Dll "Hello Word" qui deviendra celle de wrapping.
    Il sera peut-être possible de fusionner les Dll de wrapping et la "vraie" Dll mais chaque chose en son temps.

    J'ai donc ajouté tous les fichiers d’en tête et mon header créer initialement à un projet C/C++ pour DLL sur netbeans.
    Ok pour le header créé via les outils proposés par le lien dans mon dernier post, c'était un peu le but de la manœuvre.
    MAIS, ce n'est pas tous les fichiers d’en tête du projet "Code-Source.com" qu'il faut utiliser, juste les .h correspondant à l'API C de la Dll.
    Si c'est bien fait, c'est seul et unique fichier d'en-tête qu'il faut ajouter.
    Mais comme déjà indiqué, j'arrive plus à voir où est l'URL vers le projet dans "Code-Source.com".

    Le but de créer une Dll de wrapping en C via les outils de génération JNI, c'est de pas vous prendre la tête avec toutes les subtilités du C++.
    Là, vous essayez de faire la fusion de la Dll de wrapping et le code du projet "Code-Source.com" en une étape, vous allez vous cassez la figure.

    Les messages d'erreurs sont plus ou moins cohérent avec le fait que le compilateur est configuré pour du C (fichier .c).
    Le code que vous donnez dans le PDF est un .h qui n'est pas compatible C, c'est un .h de C++.
    Il est peut-être possible de configurer votre IDE pour qu'il passe en mode C++, mais je connais pas assez NetBeans pour vous diriger sur ce détail.
    Mais je pense qu'il est inutile de se complexifier le problème. N'incluez que le .h de l'API de la Dll, qui doit être compatible C, car c'est une API C que la Dll exporte.

    L'approche par étape :
    - Une Dll générées avec les outils JNI pour faire un "Hello Word" => Dll de wrapping, et tester avec votre code JAVA.
    - Ajouter au code de la Dll de wrapping un include vers le fichier .h spécifiant l'API C de la "vraie" Dll et ajouter dans la configuration de votre éditeur de lien (dans l'IDE) l'un des .lib qui doit faire partie des livrables de la Dll compatible avec votre linker (voir plus ci-après pour les problèmes de compatibilité). Et tester avec votre code JAVA.

    En écrivant la dernière étape, sur l'utilisation des .lib. Il y a un problème qui peut arriver, c'est que ce .lib ne soient pas compatible avec le linker que vous utilisez.
    De mes souvenirs, il y a une extension à Excell, je pense donc que le compilateur/linker utilisé pour cette Dll est VC++.
    MinGw et VC++ n'ont pas le même format de .lib.
    Pour utiliser facilement VC++, on se sert de Visual Studio.
    VS Express Edition est gratuit et VS Community Edition est gratuit pour les particuliers et les TPE.
    Vous pouvez vous servir de Visual Studio pour générer directement la Dll de Wrapping, ou peut-être utiliser le VC++ depuis NetBeans.
    Sinon, il faudra générer un .lib compatible avec MinGw soit à partir du .lib pour VC++, soit à partir du .def des sources, soit en recompilant toute la Dll depuis MinGw.

  8. #8
    Nouveau Candidat au Club
    Homme Profil pro
    Développeur COBOL
    Inscrit en
    Février 2017
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur COBOL
    Secteur : Finance

    Informations forums :
    Inscription : Février 2017
    Messages : 6
    Points : 0
    Points
    0
    Par défaut
    J’avoue que le concept reste assez flou dans ma tête.

    Ok pour ne pas fusionner les dll entre elles. Mais, quant à l'écriture de la dll de wrapping c'est la confusion.

    Si je comprends bien, vous me proposez de réaliser la dll "hello world" indépendamment de mon projet puis de tester son fonctionnement?
    PUIS de faire un include monproj.h dans le helloworld.h pour faire appel aux fonctions de la dll de base ? (Je pense avoir mal compris, car ça semble peu logique..)

    Mes excuses si je comprends mal, voici mes étapes:

    -- Exemple pour la première fonction généré pour le fichier header --


    launcher_Runner.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 launcher_Runner */
     
    #ifndef _Included_launcher_Runner
    #define _Included_launcher_Runner
    #ifdef __cplusplus
    extern "C" {
    #endif
    /*
     * Class:     launcher_Runner
     * Method:    al
     * Signature: (JD)D
     */
    JNIEXPORT jdouble JNICALL Java_launcher_Runner_al
      (JNIEnv *, jobject, jlong, jdouble);
     
    /*
    *
    ....
    -- l'écriture du code .c --

    Je reste bloquer a cette étape, je ne sais pas quoi mettre dedans, car les fonctions du fichier "Stable.cpp" du livrable son en c++ donc pas compatible pour ma dll de wrapping. Ce qui génère également des erreurs dans les paramètres..

    N'incluez que le .h de l'API de la Dll, qui doit être compatible C, car c'est une API C que la Dll exporte

    Si une chose est pire que le brouillard, j'y suis

  9. #9
    Expert éminent sénior
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2005
    Messages
    5 073
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2005
    Messages : 5 073
    Points : 12 119
    Points
    12 119
    Par défaut
    Pas de panique, ce n'est pas si compliqué et vous n'êtes pas si loin.

    Si je comprends bien, vous me proposez de réaliser la dll "hello world" indépendamment de mon projet puis de tester son fonctionnement?
    C'est plus pour gérer 2 difficultés, l'une après l'autre.

    Faire une Dll "hello word", c'est pour être sûr qu'on sache faire un appel JNI correctement.
    Une simple fonction C "HelloWord" qui renvoie un simple "Hello Word", ça doit être ce qui se fait de plus simple, non ?
    Avec l'extrait de code que vous nous avez posté, on ne va pas prendre "HelloWord" mais votre "Java_launcher_Runner_al", parce que vous devez déjà avoir le code JAVA capable de l'appeler et de recevoir le résultat.
    OK ?

    Une fois que l'on sait faire appel à une fonction dans une Dll par un appel JNI, on passe à la difficulté suivante, rendre l'API de l'autre Dll accessible depuis notre code C.
    Là, c'est plus un problème de conception que de codage en tant que tel.

    PUIS de faire un include monproj.h dans le helloworld.h pour faire appel aux fonctions de la dll de base ? (Je pense avoir mal compris, car ça semble peu logique..)
    Là, c'est assez ambigu.
    "monproj.h" c'est quoi ?
    Le .h de la Dll que vous voulez utiliser ?
    Le .h généré par JNI pour l'API JAVA - C ?

    De plus, utiliser une Dll, c'est pas juste ajouter un "#include".
    Ce "#include" permet de faire des appels aux choses déclarées dans ce fichier .h quand on compile, mais il faut aussi le code binaire associé à ces choses lors de l'édition de lien, c'est là qu'intervient le .lib associé à la Dll.
    Je vous laisse regarder dans votre chaine logiciel comment ajouter les .lib nécessaire à l'édition de lien des Dll.

    P.S.: je viens de regarder les sources, ils fournissent le .dll mais pas le .lib, ces sagouins. Vous avez 2 options "simple" pour générer ce .lib :
    - soit recompiler la Dll à partir des sources, de préférence avec le même compilateur que le compilateur qui générera la Dll de wrapping
    avec tous les risques d'incompatibilité que cela peut entrainer au niveau du code source qui n'est pas forcement portable d'un compilateur à un autre.
    - soit générer un .lib ou un autre format de code binaire compatible avec votre chaine de compilation à partir du .def fourni. Votre chaine de compilation doit disposer des outils de génération de codes binaires à partir d'un .def.

    Une 3ème options, c'est faire du code à base de LoadLibrary(https://msdn.microsoft.com/en-us/lib...or=-2147217396) et de "GetProcAddress" ( https://msdn.microsoft.com/en-us/lib...or=-2147217396 ), mais c'est assez relou à utiliser.

    Avec vos questions, je pense que vous bloquez sur la première étape.
    On va se focaliser sur cette 1ère étape,"helloWord", dans la suite de la réponse.

    Vous avez généré le .h avec tout ce décorum imbuvable de JNI. C'est le truc le plus tricky et l'outil de génération le fait pour vous, c'est cool.
    Maintenant, vous n'avez qu'à implémenter dans le .c ou .cpp les trucs qu'il a déclarés dans le .h.

    Donc si le .h c'est :
    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 launcher_Runner */
     
    #ifndef _Included_launcher_Runner
    #define _Included_launcher_Runner
    #ifdef __cplusplus
    extern "C" {
    #endif
    /*
     * Class:     launcher_Runner
     * Method:    al
     * Signature: (JD)D
     */
    JNIEXPORT jdouble JNICALL Java_launcher_Runner_al
      (JNIEnv *, jobject, jlong, jdouble);
     
    /*
    *
    ....
    }
    Le .c pour implémenter ça :
    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
     
    #include "launcher_Runner.h"
     
    #ifdef __cplusplus
    extern "C" {
    #endif
     
    /*
     * Class:     launcher_Runner
     * Method:    al
     * Signature: (JD)D
     */
    JNIEXPORT jdouble JNICALL Java_launcher_Runner_al
      (JNIEnv * env, jobject thisObject, jlong p1, jdouble p2)
    {
        return p2;
    }
     
    ....
    }
    Ici, c'est une version "helloWord" de la fonction "Java_launcher_Runner_al" qui renvoie bêtement son 2ème paramètre (j'ai pris ça parce que les types sont identiques histoire de ne pas se prendre la tête).

    Une fois que vous avez bien une version "brainless" de vos "Java_launcher_RunnerXXX" qui soient appelables depuis JAVA, il faut passer à la seconde étape : Remplacer le code débile qui renvoie des trucs totalement faux par du code qui utilise l'autre Dll.
    Alors ici, c'est pas jojo.
    On sent bien que le code a été pensé avec à l'esprit d'être soit d'être appelé par du code VB6 soit en utilisant la fameuse "3ème" options dont je parle dans le P.S. au début de ce post : LoadLibrary/GetProcAddress bien vieillot.
    Pour contourner cet archaïsme, vous n'avez qu'à créer de toute pièce un fichier .h qui déclare les fonctions définis dans "Stable.cpp" :
    Donc à l'arrache "Stable.h" devrait ressembler à :
    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
     
    #ifndef _Stable_h
    #define _Stable_h
    #ifdef __cplusplus
    extern "C" {
    #endif
     
    double _stdcall al(int T,double* data );
    double _stdcall bt(int T,double* data  );
    double _stdcall sg(int T,double* data  );
    double _stdcall mm(int T,double* data  );
    double _stdcall cd(int T, double* data);
    double _stdcall betas(int T, double* data);
    double _stdcall covr(int T, double* data);
    double _stdcall acrr(int T, double* data);
    double _stdcall Stbl(double m, double g, double b, double a);
    double _stdcall StableP(double x, double m, double g,double b,  double a);
    double _stdcall StableF(double x, double m, double g, double b, double a);
     
    #ifdef __cplusplus
    }
    #endif
     
    #endif //Stable_h
    Vous ajoutez un '#include "Stable.h"' au début de votre .cpp et vous pourrez directement appeler les méthodes de la Dll dans votre code C++ de votre wrapper.
    Il reste à donner les modules binaire (.lib ou autres) à votre éditeur de lien, cf. mon P.S. précédent dans ce post.

    Aller Courage, ça y est presque.

  10. #10
    Nouveau Candidat au Club
    Homme Profil pro
    Développeur COBOL
    Inscrit en
    Février 2017
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur COBOL
    Secteur : Finance

    Informations forums :
    Inscription : Février 2017
    Messages : 6
    Points : 0
    Points
    0
    Par défaut
    Après une longue période de stand-by, je reviens vers vous.

    J'ai suivi vos directives et il me semble que la logique soit correcte.
    Je bloquais effectivement sur cette première étape. (et bloquerai surement sur d'autre )

    ETAPE-1 : J'ai généré le .h, puis créer le code .c en m'aidant du .h .
    (le .c n'a pas de corps particulier, il est brainless)
    ETAPE-2 : La, je définis chaque fonction dans le 'Stable.h' que je créer (non livré avec le source de la dll de base).

    Code :
    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
     
     #ifndef _Stable_h
    #define _Stable_h
    #ifdef __cplusplus
    extern "C" {
    #endif
     
    double _stdcall al(int T,double* data );
    double _stdcall bt(int T,double* data  );
    double _stdcall sg(int T,double* data  );
    double _stdcall mm(int T,double* data  );
    double _stdcall cd(int T, double* data);
    double _stdcall betas(int T, double* data);
    double _stdcall covr(int T, double* data);
    double _stdcall acrr(int T, double* data);
    double _stdcall Stbl(double m, double g, double b, double a);
    double _stdcall StableP(double x, double m, double g,double b,  double a);
    double _stdcall StableF(double x, double m, double g, double b, double a);
     
    #ifdef __cplusplus
    }
    #endif
     
    #endif //Stable_h
    J'ajoute le #include "Stable.h" dans mon .c qui appelle la dll de base.
    Vous ajoutez un '#include "Stable.h"' au début de votre .cpp et vous pourrez directement appeler les méthodes de la Dll dans votre code C++ de votre wrapper.
    ETAPE-3 : Les modules binaires. C’est là que ça redevient complexe.

    Il reste à donner les modules binaires (.lib ou autres) à votre éditeur de lien, cf. mon P.S. précédent dans ce post.
    - En suivant votre PS. J'utilise la 3e méthode, qui est LoadLibrary & GetProcAddress.
    En cherchant un peu sur le forum, j’ai trouvé un modèle qui m’a permis d’écrire ma première fonction avec les fameuses fonctions loadlibrary & getprocaddress.
    Ma première fonction « al » :
    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
    25
    26
    27
     
    #include "launcher_Runner.h"
    #include "Stable.h"
    #include <stdio.h> 
    #include <windows.h>typedef double (__stdcall *AL)(long,double*);                            //pointeur de fonction al dans Stable.dll
    //
    JNIEXPORT jdouble JNICALL Java_launcher_Runner_al
      (JNIEnv * env, jobject thisObject, jlong T, jdouble data)
    {
        HINSTANCE dll;
        AL al;
     
        double resultat;
        if ((dll=LoadLibrary("Stable.dll"))) {                                      //chargement de la dll
        al = GetProcAddress(dll, "al");                                             //chargement de la méthode
            if (al) {
                resultat = al(T,data);                                              //appel de la méthode         
            }else{
                    printf("Fonction introuvable");
            }
            FreeLibrary(dll);                                                       //libération de l'autre dll
        }
        return resultat;
     
    }
    Finalement avant de continuer dans mon élan sur les autres fonctions, je voudrais lever un doute sur l’exactitude de ce code... Il me semble étrange d’appeler si simplement la fonction « al » de la dll de base. J’ai peut-être fait une erreur là-dessus ? ou pas...

    Sinon, comme indiqué également dans votre PS, cette 3éme méthode est lourde en code. Que me conseillez-vous ? Partir sur du loadlibrary & getprocaddress ou la deuxième méthode (avec le .lib), qui semble moins contraignante ?

  11. #11
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Pour commencer, ça fait bizarre de refaire les LoadLibrary() et FreeLibrary() à chaque fois, je te conseille d'avoir un truc genre une méthode Initialize() et Close().

    Ensuite, tu pourrais t'inspirer des fonctions virtuelles de C++: Te faire une table que tu remplirais une fois pour toute dans ta fonction Initialize() avec toutes les adresses de fonction...
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  12. #12
    Nouveau Candidat au Club
    Homme Profil pro
    Développeur COBOL
    Inscrit en
    Février 2017
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur COBOL
    Secteur : Finance

    Informations forums :
    Inscription : Février 2017
    Messages : 6
    Points : 0
    Points
    0
    Par défaut
    ca ne me dérange pas de faire votre proposition, mais je rappel que je novice sur c++.

    Par conséquent, je ne connais pas du tout les méthodes Initialize() et Close(), et comment les utiliser dans le cadre de mon projet.
    (j'ai un peu chercher, mais sans succès pour le moment..)

    Si vous pouvez me donner une bonne base et quelques conseil, je suis open.

    Encore une fois, est-ce vraiment judicieux de passer par du getprocaddress et loadlibrary? ou passer par la génération d'un .lib via netbeans et le .def ..?

    merci pour votre aide!

  13. #13
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Citation Envoyé par papaella Voir le message
    Par conséquent, je ne connais pas du tout les méthodes Initialize() et Close(), et comment les utiliser dans le cadre de mon projet.
    (j'ai un peu chercher, mais sans succès pour le moment..)
    C'est pas vrai...

    Je parlais de créer une fonction dans ta DLL, l'appeler Initialize(), Demarrage() ou même MonCul() si ça te chante, et y mettre ton code de LoadLibrary() etc.!
    Puis t'assurer d'appeler cette fonction en premier.

    Un truc du genre:

    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
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    static HMODULE g_loadedLib = NULL;
     
    #define INITRET_OK (0)
    #define INITRET_ALREADY (-1)
    #define INITRET_LOAD_FAIL (-2)
     
    JNIEXPORT jint JNICALL Java_launcher_Runner_Initialize(JNIEnv * env, jobject thisObject)
    {
    	if(g_loadedLib != NULL)
    		return INITRET_ALREADY;
    	g_loadedLib = LoadLibrary("Stable.dll");
    	if(g_loadedLib == NULL)
    		return INITRET_LOAD_FAIL;
    	return INITRET_OK;
    }
     
    JNIEXPORT jint JNICALL Java_launcher_Runner_Close(JNIEnv * env, jobject thisObject)
    {
    	if(g_loadedLib != NULL) {
    		FreeLibrary(g_loadedLib);
    		g_loadedLib = NULL;
    	}
    	return 0;
    }
     
    /*Note: AL prend un seul double ou plusieurs?
    si c'est plusieurs, alors c'est plutôt un jdoubleArray que tu devras utiliser.
    Et il faudra faire des conversions, peut-être même des copies du tableau... */
    JNIEXPORT jdouble JNICALL Java_launcher_Runner_al
      (JNIEnv * env, jobject thisObject, jlong T, jdouble data)
    {
    	AL al = NULL;
     	double resultat = 0;
    	if(g_loadedLib == NULL)
    		return 0;
     
    	al = GetProcAddress(g_loadedLib, "al"); //chargement de la méthode
            if(al != NULL) {
    		resultat = al(T, &data);        //appel de la méthode         
            } else {
    		printf("Fonction introuvable");
    	}
    	return resultat;
    }
    Note: ce code n'est pas du tout thread-safe, au passage. Il n'a pas vocation à l'être.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  14. #14
    Expert éminent sénior
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2005
    Messages
    5 073
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2005
    Messages : 5 073
    Points : 12 119
    Points
    12 119
    Par défaut
    Ok.

    Pour faire un peu d'explication de texte du message de @Médinoc, il n'a indiqué les méthodes "Initialize() et Close()" que comme noms "d'exemple", à titre indicatif.
    Ce qui le choque une personne "expérimentée" en chargement de dll dynamiquement, c'est que le traitement derrière "LoadLibrary" et "FreeLibrary" est extrêmement lourd d'un point de vue de l'OS : Lire les informations sur la Dll à charger dans l'en-tête du fichier, trouver des zones mémoire pour y copier le code exécutable et autres bidules de la Dll, y copier ces bidules, modifier le code binaire pour qu'il colle aux zones mémoire trouvées (code "relogeable" des Dll), mettre à jour les structures de données de management de la mémoire pour prendre en compte cette dll "injectée" dans le processus.
    Pour "FreeLibrary", c'est un peu moins lourd, mettre à jour les structures de données de management de la mémoire après avoir tout désallouer.
    Donc faire tout cela à chaque appel, c'est un ENORME gâchis de ressource.

    L'"astuce" habituel, c'est de ne faire le "LoadLibrary" que dans une fonction dédiée, nommée "Initialize", "Open" ou "MaGrandMereEnPatin", c'est selon vos habitudes.
    En symétriquement, faire le "FreeLibrary" dans une autre fonction dédiée, nommée "Uninitialize", "Close" ou "MaGrandMereEnPatin2", c'est selon vos habitude (enfin, ils y en a de plus simple que d'autres ).
    Après, dans la documentation d'utilisation des fonctions du wrapper, vous indiquez que l'utilisateur de ces fonctions doivent appeler la fonction "Initialize" (ou autre, en fonction de vos choix "habituels") avant tout usage d'autres fonctions du wrapper et d'appeler "Uninitialize" après la fin de l'utilisation des fonctions du wrapper.
    Toujours penser à la réutilisabilité de chose, donc documentation.
    Même si vous n'êtes le seul utilisateur de votre wrapper, et que cela ressemble à de la schizophrénie, le "vous" dans 6 mois vous en sera gré d'avoir correctement documenté ce wrapper.
    Attention au faux ami "DllMain", cette fonction est appelée dans un contexte d'exécution où toutes les étapes de chargement d'une Dll ne sont pas encore terminé et où l'appel à un "LoadLibrary" plante/freeze très souvent.
    C'est pour ça que les fonctions à la "Initialize() et Close()" sont plus safe.

    Quant au concept de "fonctions virtuelles de C++", c'est un peu "hardcore" pour un "novice C++".
    Pour faire simple, généralement, les compilateurs C++ mettent les "fonctions virtuelles" d'une classe dans un tableau de pointeur de fonctions appelées V_Table (pour virtual table).
    Ce que veut dire @Médinoc, je pense, c'est que vous pouvez remplir un tableau de pointeur de fonction dans le "Initialize" (ou "Open" ou "MaGrandMereEnPatin" ) car vous savez combien vous aurez de pointeur de fonction (le nombre de fonction exportée par la Dll) et l'adresse de ces fonctions ne changera pas tant que la Dll n'est pas déchargée puis rechargée.
    Donc, il serait plus pratique de faire le LoadLibrary et tous les GetProcAddress dans la fonction "Initialize" (ou ....) et stocker les valeurs retournées par GetProcAddress dans ce tableau.
    Les autres fonctions du wrappeur n'auront cas casté la valeur stockée dans ce tableau "global".

    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
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    #include "launcher_Runner.h"
    #include "Stable.h"
    #include <stdio.h> 
    #include <windows.h>typedef double (__stdcall *AL)(long,double*);                            //pointeur de fonction al dans Stable.dll
    //
     
    HINSTANCE dll;
    FARPROC* functions;
     
    JNIEXPORT void JNICALL Initialize
      (JNIEnv * env, jobject thisObject)
    {
        if ((dll=LoadLibrary("Stable.dll"))) {
            functions = malloc(sizeof(FARPROC)*NB_Functions);
            functions[0] = GetProcAddress(dll, "al");
            functions[1] = GetProcAddress(dll, "bt");
    ...
        }
        else{
            dll = NULL;
            functions = NULL;
        }
    }
     
    JNIEXPORT void JNICALL Uninitialize
      (JNIEnv * env, jobject thisObject)
    {
        FreeLibrary(dll);
        dll = NULL;
        free(functions);
    }
     
    //
    JNIEXPORT jdouble JNICALL Java_launcher_Runner_al
      (JNIEnv * env, jobject thisObject, jlong T, jdouble data)
    {
        AL al = functions[0];
     
        double resultat = NAN;
        if (al) {
           resultat = al(T,data);                                              //appel de la méthode         
        }else{
                printf("Fonction introuvable");
        }
        return resultat;
     
    }
    Si vous utilisez l'approche "LoadLibrary/GetProcAddress", la construction de "Stable.h" ne sert pas (mais si vous passez aux autres solutions cela sera très utile).
    En faisant un '#include "Stable.h"', cela transformera les erreurs de compilation en erreur d'édition de lien.
    Vous aurez ce type d'erreur si vous appelez avec directement le nom des fonctions de la Dll plutôt que de passer par les fonctions du wrapper.

    Encore une fois, est-ce vraiment judicieux de passer par du getprocaddress et loadlibrary?
    C'est lourd, mais c'est un mécanisme plus simple, moins intégré, moins "magic".

    ou passer par la génération d'un .lib via netbeans et le .def ..?
    Cela serait plus simple in fine, mais la mise en place demande plus de connaissance, et moi, netbeans, je connais pas.

    Il me semble étrange d’appeler si simplement la fonction « al » de la dll de base.
    C'est déjà bien balaise, vous trouvez pas ?
    Votre code est correcte bien qu'un peu lourd (cf. le début du post).
    Il faut vérifier que cela fonctionne.
    2 choses à vérifier :
    - que les noms des fonctions ne soit pas décorées avec des trucs comme "@x" etc..., Utilisez un outil comme dependency walker pour vérifier le nom exacte des fonctions exportées.
    http://www.dependencywalker.com/
    - que les types des paramètres entre la signature JNI et la signature de la fonction soient compatible
    que le compilateur ne vous engueule pas pour un trans-typage foireux, mais aussi que ce cher C, qui adore faire entrer des ronds dans des carrés (comprendre une vérification des trans-typages des plus laxistes), n'est pas fait n'importnawak.
    Si nécessaire, il faudra faire les conversions dans un sens pour les paramètres et dans l'autre pour la ou les valeurs de retour.

    Que me conseillez-vous ? Partir sur du loadlibrary & getprocaddress ou la deuxième méthode (avec le .lib), qui semble moins contraignante ?
    Vue que vous n'avez que 11 fonctions, que vous avez déjà bien maitrisez le "LoadLibrary/GetProcAddress" et que vous risquez de galérer seul avec la création d'un lib à partir d'un .def (qui reste à faire, je crois), je pense que l'approche relou du "LoadLibrary/GetProcAddress" fera assez bien l'affaire car vos fonctions semble bien indépendantes.

  15. #15
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Merci, Bacelar.

    Je voudrais juste ajouter une info: Plutôt qu'un tableau, on peut faire une structure:

    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
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    struct functionsTable
    {
    	double (_stdcall *al)(int T,double* data );
    	double (_stdcall *bt)(int T,double* data  );
    	double (_stdcall *sg)(int T,double* data  );
    	double (_stdcall *mm)(int T,double* data  );
    	double (_stdcall *cd)(int T, double* data);
    	double (_stdcall *betas)(int T, double* data);
    	double (_stdcall *covr)(int T, double* data);
    	double (_stdcall *acrr)(int T, double* data);
    	double (_stdcall *Stbl)(double m, double g, double b, double a);
    	double (_stdcall *StableP)(double x, double m, double g,double b,  double a);
    	double (_stdcall *StableF)(double x, double m, double g, double b, double a);
    };
     
    void Erreur(char const *msg)
    {
    	fprintf(stderr, "%s\n", msg);
    }
     
    void InitFunctionTable(HMODULE hLibrary, struct functionsTable *pTable)
    {
    	if(hLibrary == NULL) {
    		Erreur("Bibliothèque non chargée.");
    		return;
    	}
     
    	pTable->al = (double (_stdcall*)(int, double*)) GetProcAddress(hLibrary, "al");
    	pTable->bt = (double (_stdcall*)(int, double*)) GetProcAddress(hLibrary, "bt");
    	pTable->sg = (double (_stdcall*)(int, double*)) GetProcAddress(hLibrary, "sg");
    	pTable->mm = (double (_stdcall*)(int, double*)) GetProcAddress(hLibrary, "mm");
    	pTable->cd = (double (_stdcall*)(int, double*)) GetProcAddress(hLibrary, "cd");
    	pTable->betas = (double (_stdcall*)(int, double*)) GetProcAddress(hLibrary, "betas");
    	pTable->covr = (double (_stdcall*)(int, double*)) GetProcAddress(hLibrary, "covr");
    	pTable->acrr = (double (_stdcall*)(int, double*)) GetProcAddress(hLibrary, "acrr");
    	pTable->Stbl = (double (_stdcall*)(double, double, double, double)) GetProcAddress(hLibrary, "Stbl");
    	pTable->StableP = (double (_stdcall*)(double, double, double, double, double)) GetProcAddress(hLibrary, "StableP");
    	pTable->StableF = (double (_stdcall*)(double, double, double, double, double)) GetProcAddress(hLibrary, "StableF");
     
    	if(pTable->al == NULL) Erreur("Echec pour fonction 'al'.");
    	if(pTable->bt == NULL) Erreur("Echec pour fonction 'bt'.");
    	if(pTable->sg == NULL) Erreur("Echec pour fonction 'sg'.");
    	if(pTable->mm == NULL) Erreur("Echec pour fonction 'mm'.");
    	if(pTable->cd == NULL) Erreur("Echec pour fonction 'cd'.");
    	if(pTable->betas == NULL) Erreur("Echec pour fonction 'betas'.");
    	if(pTable->covr == NULL) Erreur("Echec pour fonction 'covr'.");
    	if(pTable->acrr == NULL) Erreur("Echec pour fonction 'acrr'.");
    	if(pTable->Stbl == NULL) Erreur("Echec pour fonction 'Stbl'.");
    	if(pTable->StableP == NULL) Erreur("Echec pour fonction 'StableP'.");
    	if(pTable->StableF == NULL) Erreur("Echec pour fonction 'StableF'.");
    }
     
    JNIEXPORT void JNICALL Initialize(JNIEnv * env, jobject thisObject)
    {
    	if ((dll=LoadLibrary("Stable.dll"))) {
    		functions = malloc(struct functionsTable);
    		InitFunctionTable(dll, functions);
    	} else{
    		dll = NULL;
    		functions = NULL;
    	}
    }
    PS:
    Citation Envoyé par bacelar
    que vous risquez de galérer seul avec la création d'un lib à partir d'un .def (qui reste à faire, je crois)
    Si le GetProcAddress(dll, "al") marche alors que al est en _stdcall, ça suggère que le .def existe déjà.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  16. #16
    Expert éminent sénior
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2005
    Messages
    5 073
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2005
    Messages : 5 073
    Points : 12 119
    Points
    12 119
    Par défaut
    Si le GetProcAddress(dll, "al") marche alors que al est en _stdcall, ça suggère que le .def existe déjà.
    Oui, mais c'est le ".lib/.a" qui reste à faire.

Discussions similaires

  1. Dll C++ pour VBA
    Par hadGP dans le forum Visual C++
    Réponses: 15
    Dernier message: 30/11/2014, 01h56
  2. [Débutant] dll VB.NET pour VBA
    Par issoram dans le forum VB.NET
    Réponses: 7
    Dernier message: 26/09/2013, 20h42
  3. compiler du vba pour faire une dll (ou equivalent)
    Par emmesse2 dans le forum Macros et VBA Excel
    Réponses: 7
    Dernier message: 24/11/2008, 10h09
  4. dll C++ pour VBA : erreur 49 et 453
    Par EL0807 dans le forum C++
    Réponses: 2
    Dernier message: 18/03/2006, 23h01

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