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 :

MinGW, DLL externe, DEF, LIB, a. Je sèche.


Sujet :

C++

  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    26
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2009
    Messages : 26
    Points : 23
    Points
    23
    Par défaut MinGW, DLL externe, DEF, LIB, a. Je sèche.
    Bonjour.
    Pour un de mes projets écrit avec code::blocks + wxWidget + MinGW, tous dans leur version récente, je dois faire appel à des fonctions disponibles dans une DLL fournie par un tiers.
    Je dispose du fichier DLL, du fichier .h des fonctions disponibles, du fichier LIB, et après quelques efforts, j'ai réussi à extraire le fichier DEF avec l'outil dlltool de MinGW32

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    LIBRARY "EQ2008_Dll.dll"
    EXPORTS
    User_CloseScreen@@YGHH@Z
    User_ReadScreen@@YGHHPAUHDC__@@@Z
    Je n'arrive pas à linker correctement cette DLL dans mon projet. L'édition de lien me donne systématiquement une erreur à chaque appel de fonction dans la DLL: undefined reference to `_imp___Z16User_CloseScreeni@4'
    Mon projet est compilé avec MinGW, donc j'utilise des fichiers .a pour linker, alors que la DLL est livré avec un fichier.LIB
    Ce que j'ai essayé:
    - renommer le .LIB en .a: ne marche pas
    - inclure la DLL dans les bibliothèque à linker (avec les autres .a du projet): ne marche pas
    - extraire de la DLL le .a avec reimp.exe: ne marche pas. J'obtiens un .a vide

    Bref, je sèche. Avant de modifier le projet pour appeler directement les fonctions en lisant la DLL en dynamique lors de l'exécution (mon plan B !), j'aimerai savoir si vous avez des idées sur mon problème ?
    Comment convertir un .LIB ou .def en .a compatible avec MinGW ?
    Peut-on dans code::blocks directement linker une DLL sans le .a ?

  2. #2
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 629
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 629
    Points : 30 692
    Points
    30 692
    Par défaut
    Salut,

    Normalement, si tu as réussi à obtenir le fichier def, il te "suffit" d'un
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    dlltool -k --outputlib libEQ2008_Dll.a --def lefichier.def
    (j'ai utilisé le nom de la dll comme base pour le nom du fichier *.a ) pour créer une bibliothèque d'importation.

    Il faudra, par la suite, veiller:
    1. à ce que gcc (g++ ) connaisse le chemin d'accès aux fichiers d'en-tête en ajoutant l'argument (c'est un i majuscule )à la ligne de commande (ou en ajoutant le dossier en question dans les options de Code::Blocks)
    2. à ce que ld (l'éditeur de liens) connaisse le chemin d'accès au dossier contenant le lib*.a en ajoutant l'argument
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      -Lchemin/vers/dossier/de/lib
      à la ligne de commande (ou en ajoutant le dossier en question dans les options de Code::Blocks)
    3. veiller à ce que ld (toujours l'éditeur de liens ) effectue bien l'édition de lien avec la bibliothèque en question en ajoutant l'argument (c'est un L minuscule ) à la ligne de commande ou en ajoutant la bibliothèque en question dans les options de Code::Blocks)
    4. à ce que l'exécutable puisse accéder à la dll, soit en la plaçant dans le même dossier de l'exécutable, soit en la plaçant dans un dossier connu de la variable PATH

  3. #3
    Membre à l'essai
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    26
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2009
    Messages : 26
    Points : 23
    Points
    23
    Par défaut Merci de te pencher sur mon problème..
    Citation Envoyé par koala01 Voir le message
    Salut,

    Normalement, si tu as réussi à obtenir le fichier def, il te "suffit" d'un
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    dlltool -k --outputlib libEQ2008_Dll.a --def lefichier.def
    (j'ai utilisé le nom de la dll comme base pour le nom du fichier *.a ) pour créer une bibliothèque d'importation.
    Justement, c'est là où j'ai un problème.
    Bien sûr, le fichier EQ2008_Dll.def existe dans le répertoire de dlltool et est rempli avec les définitions.
    Lorsque j'entre cette commande
    dlltool -v -k -d EQ2008_Dll.def -l EQ2008_Dll.a
    ,j'ai bien un fichier EQ2008_Dll.a qui est créé, mais il est vide. Taille: 0K, et ouvert avec Notepad++, pas un seul petit octet à lire....
    Même chose en essayant la version de dlltool dans mingw32.
    Je pense que si j'arrive à obtenir un fichier .a non-vide, j'aurai progressé, mais là quelque chose m'échappe.
    Bien sûr, le fichier EQ2008_Dll.def existe dans le répertoire de dlltool et est rempli avec les définitions.
    Le fichier complet (avec -v) est celui-ci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    dlltool: Processing def file: EQ2008_Dll.def
    dlltool: LIBRARY: EQ2008_Dll.dll base: ffffffff
    dlltool: Processed def file
    dlltool: Processing definitions
    dlltool: Processed definitions
    dlltool: Creating library file: EQ2008_Dll.a
    dlltool: run: as   -o daqh.o daqh.s
    dlltool: No such file or directory
    dlltool: CreateProcess
    Après vérification, le fichier .s est bien créé, mais pas le .o

  4. #4
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 629
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 629
    Points : 30 692
    Points
    30 692
    Par défaut
    Attention, une bibliothèque lib*.a n'est absolument pas un fichier que l'on peut ouvrir avec notepad...

    Il s'agit, en réalité, d'une archive (créée avec ar), que l'on peut, éventuellement, ouvrir avec 7zip ou winrar, qui contient un certain nombre de fichiers objets ( *.o ).

    Ceci dit, en créant le fichier eq2008_Dll.def sous la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    LIBRARY "EQ2008_Dll.dll"
    EXPORTS
    User_CloseScreen@@YGHH@Z
    User_ReadScreen@@YGHHPAUHDC__@@@Z
    et, en lançant la commande
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    dlltool.exe -k --output-lib libeq2008_dll.a --def eq2008_dll.def -v
    j'obtiens la sortie
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    c:\temp-32bits\bin\dlltool.exe: Using file: c:\temp-32bits\bin\as
    c:\temp-32bits\bin\dlltool.exe: Processing def file: eq2008_dll.def
    c:\temp-32bits\bin\dlltool.exe: LIBRARY: EQ2008_Dll.dll base: ffffffff
    c:\temp-32bits\bin\dlltool.exe: Processed def file
    c:\temp-32bits\bin\dlltool.exe: Processing definitions
    c:\temp-32bits\bin\dlltool.exe: Processed definitions
    c:\temp-32bits\bin\dlltool.exe: Creating library file: libeq2008_dll.a
    c:\temp-32bits\bin\dlltool.exe: run: c:\temp-32bits\bin\as   -o dyskh.o dyskh.s
    c:\temp-32bits\bin\dlltool.exe: run: c:\temp-32bits\bin\as   -o dyskt.o dyskt.s
    c:\temp-32bits\bin\dlltool.exe: Creating stub file: dysks00000.o
    c:\temp-32bits\bin\dlltool.exe: Creating stub file: dysks00001.o
    c:\temp-32bits\bin\dlltool.exe: Created lib file
    et un fichier libeq_2008_dll.a de 4 ko octets contenant (ouvert avec 7zip), effectviement les fichiers objets
    • dyskh.o
    • dyskt.o
    • dysks00000.o
    • dysks00001.o
    Ce résultat est obtenu à partir de la version "personnelle" de dlltool compilée a mano:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     dlltool.exe -V
    GNU c:\temp-32bits\bin\dlltool.exe (GNU Binutils) 2.20.51.20100125
    Copyright 2010 Free Software Foundation, Inc.
    This program is free software; you may redistribute it under the terms of
    the GNU General Public License version 3 or (at your option) any later version.
    This program has absolutely no warranty.
    Nota: le fichier *.def utilisé est écrit au format *nux (fin de ligne marqué avec lf)

    Il y a, effectivement, un problème si le fichier est au format DOS (fin de ligne signalé par CRLF)...

    As tu essayé en créant le fichier def avec gendef qui semble éviter ce problème
    [EDIT]Il ne faut pas de fichier *.s... il s'agit de l'extension utilisée pour la création de fichier assembleur temporaire, utiles à la création des fichiers objets

  5. #5
    Membre à l'essai
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    26
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2009
    Messages : 26
    Points : 23
    Points
    23
    Par défaut Je progresse..
    Merci de votre aide.J'avance.
    Mais je ne suis pas encore au bout..

    Mon problème pour générer le .a venait de deux installations de dlltool, toutes deux visibles par PATH. Je suppose que as.exe s'emmêlait les pinceaux.

    Maintenant, j'ai mon .a que je link avec mon projet.
    Mais toujours cette erreur:
    undefined reference to `_imp___Z15User_OpenScreeni@4'

    Le fichier .h de la DLL:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    #define DLL_API _declspec(dllimport)
    DLL_API BOOL __stdcall User_OpenScreen(int CardNum);
    Mon appel à la fonction dans mon projet cpp:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    User_OpenScreen(m_CardNum);
    Rappel: Le contenu du .def
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    LIBRARY "EQ2008_Dll.dll"
    EXPORTS
    User_OpenScreen@@YGHH@Z
    et enfin la commande ayant servi à générer le .a:
    dlltool -v -k -d EQ2008_Dll.def -l EQ2008_Dll.a

    Je soupconne qu'il s'agit d'une différence au niveau du nom de ma fonction, mais je ne suis pas assez calé pour trouver l'erreur.
    Je vais poser la question dans la section bibliothèque du forum (j'ignore comment transférer ce post dans ce forum)

  6. #6
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 629
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 629
    Points : 30 692
    Points
    30 692
    Par défaut
    As tu bien spécifié les options d'édition de liens qui étaient nécessaires (-Lchemin/vers/libEQ2008_Dll.a -lEQ2008_dll en ligne de commande ou project->build options-> linker settings ->ajouter EQ2008_dll + project->build options->search directories->linker ->ajouter le chemin vers libEQ2008_Dll.a, dans Code::blocks)

    Généralement, une référence indéfinie est le signe que l'éditeur de liens n'a pas effectué la liaison avec une bibliothèque requise.

    Cela arrive soit parce qu'il ne sait pas qu'il doit utiliser la bibliothèque en question, soit parce qu'il ne la pas trouvée dans les dossiers dans lesquels il a regardé

  7. #7
    Membre à l'essai
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    26
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2009
    Messages : 26
    Points : 23
    Points
    23
    Par défaut Je progresse, hélas....
    Car plus j'avance dans mon problème, plus les choses deviennent compliquées.
    Pour résumer ce que j'ai découvert jusqu'ici:
    1) reimp ne marche pas avec mon .lib (invalid or corrupt import library). J'ai extrait les définitions avec pexports.exe et obtenu un fichier .def.
    2) avec cette commande:
    dlltool -v -D EQ2008_Dll.dll -d EQ2008_Dll.def -l libeqdll.a
    j'obtiens un fichier .a . Il est indispensable de préfixer le nom par 'lib' pour que ce fichier soit vu par MinGW dans les répertoires de recherche....
    La commande nm me confirme bien la présence des fonctions de la DLL dans le .a (User_AddBmp, User_OpenScreen etc..)

    Maintenant les choses amusantes:

    Le fichier .DEF:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    LIBRARY EQ2008_Dll.dll
    EXPORTS
    User_AddBmp
    User_OpenScreen
    etc..
    Lors du linkage, j'obtiens ma fameuse erreur:
    undefined reference to `_imp___Z15User_OpenScreeni@4'

    Après bien des tâtonnements, je modifie le fichier def ainsi:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    LIBRARY EQ2008_Dll.dll
    EXPORTS
    _Z15User_OpenScreeni@4
    et là, miracle et joie céleste, l'édition de lien se passe bien. Plus d'erreurs.
    Youpi ?
    Et non, au démarrage du programme, j'ai une run-time error:

    machin.exe n'a pas pu trouver la fonction '_Z15User_OpenScreeni@4' dans la dll EQ2008_Dll.DLL

    En bref, MinGW ajoute plein de truc (_Z15, i@4) aux prototypes, et ensuite s'étonne de ne pas retrouver ce qu'il a ajouté dans la DLL (qui, c.f plus haut, ne contient que des appels simples).

    Je craque un peu. Il n'en faudrait pas beaucoup plus pour me pousser à boire.

    Une idée de l'origine du problème ?

  8. #8
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 629
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 629
    Points : 30 692
    Points
    30 692
    Par défaut
    Pourrais tu nous fournir la dll que tu essaye de convertir, ou, à défaut, un lien qui nous permette de l'obtenir

    D'ailleurs, s'agit-il d'une dll écrite en C ou d'une dll écrite en C++

    Il sera en effet beaucoup plus simple pour nous de trouver une solution si nous savons exactement de quoi il retourne

  9. #9
    Membre à l'essai
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    26
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2009
    Messages : 26
    Points : 23
    Points
    23

  10. #10
    Membre expérimenté Avatar de 10_GOTO_10
    Profil pro
    Inscrit en
    Juillet 2004
    Messages
    887
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2004
    Messages : 887
    Points : 1 531
    Points
    1 531
    Par défaut
    Ya pas la dll dans ton lien... Dommage

    Sinon, une astuce que j'avais utilisé une fois est de créer de toutes pièces une Dll "fantôme" avec le compilateur de destination, les mêmes noms de fonctions exportées (fonctions qui ne feront rien du tout, peu importe), les mêmes conventions d'appel, le même nom. Le compilateur va te créer un fichier .a (dans ton cas), que tu pourra réutiliser pour appeler la vraie dll.

    Sinon, tu peux aussi utiliser ce programme, mais je crois qu'il ne marche pas trop pour exporter un .a .

  11. #11
    Membre à l'essai
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    26
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2009
    Messages : 26
    Points : 23
    Points
    23
    Par défaut Merci à tous.
    Finalement, je me suis tiré d'affaire en faisant un appel dynamique au lieu d'essayer désespérément de lier ma DLL à la compilation. Dans une autre vie, si j'ai le temps, j'irai chercher pourquoi ce #*-~ de compilateur gcc (enfin, le linker ld) me rajoute plein de @ après le nom honnête et bien identifié de ma fonction, s'empêchant lui-même de la lier.

    Mon code final:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
        typedef int __stdcall (*DLLAddTextPtr) (int CardNum,void* pt,int iProgramIndex);
        const wxString uneFonction  = wxT("User_AddText");
        if(LibLoader.HasSymbol(uneFonction))
        {
            DLLAddTextPtr pfnDLL = (DLLAddTextPtr)LibLoader.GetSymbol(uneFonction);
            if (pfnDLL)
            {
                pfnDLL(1,&Text ,1);
                SetStatusText(_("AddText fait"),0);
            }
        }
    en lieu et place de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    User_AddText(m_iCardNum,&Text,m_iProgramIndex);
    Pour la petite histoire, il m'a fallu 4 heures d'effort et de débuggage pour trouver le __stdcall nécessaire plus haut.

  12. #12
    Membre expérimenté Avatar de 10_GOTO_10
    Profil pro
    Inscrit en
    Juillet 2004
    Messages
    887
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2004
    Messages : 887
    Points : 1 531
    Points
    1 531
    Par défaut
    Citation Envoyé par AlexG34 Voir le message
    pourquoi ce #*-~ de compilateur gcc (enfin, le linker ld) me rajoute plein de @ après le nom honnête et bien identifié de ma fonction
    Ca, c'est ce qu'on appelle les "décorations". C'est pas pour faire joli , c'est censé représenter les arguments de la fonction appelée. C'est obligatoire en C++ puisque le polymorphisme autorise à avoir plusieurs fonctions avec le même nom (mais pas les mêmes arguments, bien sûr).

    Le malheur est que ce n'est pas normalisé, et donc chaque compilo a ses propres conventions de nomage.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. DLL sans .DEF ou .LIB
    Par ZJP972 dans le forum C
    Réponses: 3
    Dernier message: 05/07/2007, 22h40
  2. Appel de DLL sans .DEF ou .LIB
    Par ZJP972 dans le forum C++
    Réponses: 5
    Dernier message: 05/07/2007, 22h35
  3. dll ActiveX utilisant une DLL externe
    Par Metal3d dans le forum VB 6 et antérieur
    Réponses: 2
    Dernier message: 10/11/2005, 19h02
  4. [Jonas]Ajout de dll externes
    Par romainp22 dans le forum JOnAS
    Réponses: 8
    Dernier message: 14/01/2005, 12h41
  5. Dialogue DLL externe
    Par rgarnier dans le forum XMLRAD
    Réponses: 8
    Dernier message: 07/05/2003, 15h28

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