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 :

Passage d'objet dans une DLL


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé
    Profil pro
    Inscrit en
    Juin 2002
    Messages
    256
    Détails du profil
    Informations personnelles :
    Localisation : Etats-Unis

    Informations forums :
    Inscription : Juin 2002
    Messages : 256
    Par défaut Passage d'objet dans une DLL
    Bonjour,

    Dans mon programme, je suis en train de créer un système de plugins. Histoire de vérifier que ça fonctionne, j'ai codé quelques fonctions dans ma DLL genre "GetAuthor" :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    //HEADER (dans une classe)
    typedef void* (__stdcall *DllPtyType)(void);
    DllPtyType AuthorFc;
     
    // FICHIER CPP
    AuthorFc = LoadFunction<DllPtyType>("GetAuthor");
    La fonction LoadFunction étant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    template<class T>
    	T LoadFunction(const string& _FuncName)
    	{
    		void* Func = GetProcAddress(m_Library, _FuncName.c_str() );
     
    		return reinterpret_cast<T>(Func);
    	}
    (j'ai enlevé le check sur "Func" puisque je le gère ailleurs). Et la fonction GetAuthor :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    extern "C" __declspec(dllexport) void* GetAuthor()
    {
    	return (void*)(&g_Author);
    }
    (g_Author étant de type string). Puis je l'utilise comme suit :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    void* l_Ret;
     
    	if( AuthorFc )
    	{
    		l_Ret = AuthorFc();
    		memcpy((void*)&m_Author,l_Ret,sizeof(string));
    	}
    	else
    		m_Author = "Not specified";
    Ca fonctionne... presque. Dans la suite du programme, j'obtiens bien l'auteur. Par contre, j'ai un joli plantage (type segfault) à la fermeture. Je ne vois pas du tout d'où il vient (enfin... le memcpy qui passe mal ?).

    Et puis ce code est relativement moche : je suis obligé de passer par un castage tout moche en void* à la C. En effet, si je définie DllPtyType comme :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    typedef string (__stdcall *DllPtyType)(void);
    où que je passe un argument de type string (mais, plus généralement, un quelconque type non standard du C/C++), le code compile, mais plante à l'exécution en me disant que le registre "ESP was not saved properly...".
    Pourquoi ? Alors que je reste définitivement en C++ partout, je ne peux pas passer d'objet autrement que par un cast "sauvage" en void* ?

    merci

    Cordialement

  2. #2
    Membre éclairé
    Profil pro
    Inscrit en
    Juin 2002
    Messages
    256
    Détails du profil
    Informations personnelles :
    Localisation : Etats-Unis

    Informations forums :
    Inscription : Juin 2002
    Messages : 256
    Par défaut
    Je n'ai plus d'erreur de mémoire à la fermeture de mon programme si, au lieu de passer des string castées en void*, je passe directement des char* (qui ne peuvent d'ailleurs pas être "const").

    On va faire avec... n'empêche que ça m'étonne de pas pouvoir passer d'objet à des DLL... Je dois me tromper. Savez-vous comment faire ?

    Merci.

    Cordialement

  3. #3
    Membre éprouvé
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    1 537
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Juillet 2006
    Messages : 1 537
    Par défaut
    Il n'y a rien de particulier a faire : les objet apparaissent en C comme des structures.

  4. #4
    Membre éclairé
    Profil pro
    Inscrit en
    Juin 2002
    Messages
    256
    Détails du profil
    Informations personnelles :
    Localisation : Etats-Unis

    Informations forums :
    Inscription : Juin 2002
    Messages : 256
    Par défaut
    Alors pourquoi ce plantage ?

  5. #5
    Membre éprouvé
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    1 537
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Juillet 2006
    Messages : 1 537
    Par défaut
    Tout ce qui est alloué dans la DLL doit être désaloué dans la DLL et vice versa. A mon avis le plantage vient de la.

    Essaye de passer l'application au debuggeur histoire de voir précisément ouc a coince

  6. #6
    Membre Expert
    Avatar de Klaim
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Août 2004
    Messages
    1 717
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur de jeux vidéo
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 1 717
    Par défaut
    Ou alors vérifie que tes projets sont bien configurés correctement concernant la mémoire partagée entre exe et dll...

  7. #7
    Expert confirmé

    Homme Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Février 2007
    Messages
    4 253
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Février 2007
    Messages : 4 253
    Billets dans le blog
    3
    Par défaut
    Citation Envoyé par delire8 Voir le message
    Ca fonctionne... presque. Dans la suite du programme, j'obtiens bien l'auteur. Par contre, j'ai un joli plantage (type segfault) à la fermeture. Je ne vois pas du tout d'où il vient (enfin... le memcpy qui passe mal ?).
    Du tout... sauf que ton std::string dans le main va détruire la chaine...
    Et le unload de la DLL va faire de même....

    En même temps... si c'est pour faire du statique, autant faire un truc genre:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    Dans la dll:
     
    const char* getAuthor()
    {
       return "Author";
    }
     
    Dans le main:
     
    typedef const char* (*getAuthorProc)();
    getAuthorProc proc = ....;
    std::string toto = proc();
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    typedef string (__stdcall *DllPtyType)(void);
    .... le code compile, mais plante à l'exécution en me disant que le registre "ESP was not saved properly...".
    Pourquoi ?
    Tu es sur que la fonction de ta DLL est bien en __stdcall ? En général ce genre d'erreur ca vient de là.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    extern "C" __declspec(dllexport) string* GetAuthor()
    {
    	return &g_Author;
    }
    Il est ou le __stdcall ?
    Normalement, par défaut, c'est _cdecl qui est utilisé.

  8. #8
    Membre éclairé
    Profil pro
    Inscrit en
    Juin 2002
    Messages
    256
    Détails du profil
    Informations personnelles :
    Localisation : Etats-Unis

    Informations forums :
    Inscription : Juin 2002
    Messages : 256
    Par défaut
    Désolé pour le retard, j'étais assez occupé ces derniers jours.

    Merci pour vos réponses, je vais essayer... bientôt. Eh oui, en voulant sauvegarder mes projets, j'ai simplement formatté. Si si, c'est possible...

    Cordialement

  9. #9
    Membre éclairé
    Profil pro
    Inscrit en
    Juin 2002
    Messages
    256
    Détails du profil
    Informations personnelles :
    Localisation : Etats-Unis

    Informations forums :
    Inscription : Juin 2002
    Messages : 256
    Par défaut
    J'ai refait un projet vite-fait pour tester ta suggestion. Ca marche presque.
    Si je corrige et que je met bien __stdcall dans le prototype des fonctions exportées, eh bien mon pointeur sur fonction (initialisé par GetProcAddress) reste à NULL.

    En revanche, si j'enlève les conventions d'appel partout, tout fonctionne (y compris le retour de std::string et la modification d'un argument de type string& .

    Pourquoi cela plante avec les __stdcall et __fastcall ? D'ailleurs, qu'est-ce que changent ces préfixes ?

    Merci

    Cordialement

  10. #10
    Membre Expert

    Profil pro
    Inscrit en
    Juin 2006
    Messages
    1 294
    Détails du profil
    Informations personnelles :
    Localisation : Royaume-Uni

    Informations forums :
    Inscription : Juin 2006
    Messages : 1 294
    Par défaut
    Citation Envoyé par delire8 Voir le message
    D'ailleurs, qu'est-ce que changent ces préfixes ?
    Ils changent la manière dont est réalisé l'appel de fonction, tu peux par exemple lire Calling conventions on the x86 platform pour quelques précisions.

    MAT.

  11. #11
    Membre éclairé
    Profil pro
    Inscrit en
    Juin 2002
    Messages
    256
    Détails du profil
    Informations personnelles :
    Localisation : Etats-Unis

    Informations forums :
    Inscription : Juin 2002
    Messages : 256
    Par défaut
    Merci pour le lien, concis et clair.

Discussions similaires

  1. Problème de survol en création d'objet dans une DLL
    Par KlausGunther dans le forum Composants VCL
    Réponses: 20
    Dernier message: 07/01/2015, 12h19
  2. Réponses: 1
    Dernier message: 07/01/2010, 16h16
  3. Passage de structure dans une DLL
    Par nikoko34 dans le forum VB.NET
    Réponses: 1
    Dernier message: 18/07/2008, 10h11
  4. Réponses: 20
    Dernier message: 23/09/2005, 13h50
  5. [VB6]Passage d'un tableau dans une DLL écrite en delphi
    Par flash dans le forum VB 6 et antérieur
    Réponses: 6
    Dernier message: 20/09/2002, 10h15

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