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 :

Problème : créer une classe dans une dll et l'exporter dans une application.


Sujet :

C++

  1. #21
    En attente de confirmation mail
    Inscrit en
    Avril 2004
    Messages
    83
    Détails du profil
    Informations forums :
    Inscription : Avril 2004
    Messages : 83
    Points : 54
    Points
    54
    Par défaut
    Citation Envoyé par Laurent Gomila
    En effet, extern n'a rien à faire devant une définition de fonction membre.
    Merci bien, tout est ok

  2. #22
    En attente de confirmation mail
    Inscrit en
    Avril 2004
    Messages
    83
    Détails du profil
    Informations forums :
    Inscription : Avril 2004
    Messages : 83
    Points : 54
    Points
    54
    Par défaut
    JE reviens de nouveau avec une question sur un warning
    Celui intervient dans la compilation du .h de ma dll sur la déclaration de variable de classe private de type string ou bitset (je ne sais pas pour les autres types).
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    ...dll_paq_ts.h(39) : warning C4251: 'Paquet::HEADER_continuity_counter' : class 'std::bitset<_Bits>' nécessite une interface DLL pour être utilisé(e) par les clients de class 'Paquet'
            with
            [
                _Bits=4
            ]
    J'ai regardé l'erreur dans l'aide : il faut rajouter __declspec(dllexport) mais je ne vois pas où...

    Voici la partie de mon code qui créé des warning :
    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
    ...
    class IMPEXP Paquet
    {
    	public:
     
    		Paquet(); // Constructeur par défaut
    		~Paquet();
    ...
     
    	private:
    		string	     contenu; //A partir d'ici, un warning par ligne
    		bitset<8>	HEADER_syncbyte;
    		bitset<1>	HEADER_transport_error_indicator;
    		bitset<1>	HEADER_start_indicator;
    		bitset<1>	HEADER_transport_priority;
    		bitset<13>	HEADER_PID;
    		bitset<2>	HEADER_scrambling_control;
    		bitset<2>	HEADER_adaptation_field_control;
    		bitset<4>	HEADER_continuity_counter;
     
      };

  3. #23
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Points : 15 920
    Points
    15 920
    Par défaut
    Tu peux, au choix :
    - Ignorer cet avertissement (ça fonctionnera dans des conditions normales)
    - Exporter toutes les instanciations de std::bitset que tu utilises
    La syntaxe devrait être du genre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    template <> IMPEXP std::bitset<1>;
    template <> IMPEXP std::bitset<2>;
    ...
    - Ne pas faire apparaître de classe non exportée dans l'interface de tes classes exportées (c'est pas toujours pratique...)

  4. #24
    En attente de confirmation mail
    Inscrit en
    Avril 2004
    Messages
    83
    Détails du profil
    Informations forums :
    Inscription : Avril 2004
    Messages : 83
    Points : 54
    Points
    54
    Par défaut
    Merci encore Laurent, je vais ignorer si ca n'a pas d'incidence.

    J'ai ENCORE un soucis J'essaie de faire pas mal de truc et de m'exercer à manipuler des dll donc c'est normal que je rencontre des problèmes. Voici celui auquel je suis confronté.

    J'ai 2 DLL : DLL1 et DLL2.
    Dans une classe de ma DLL1, je déclare un public bool "arret_des_threads". Ce public bool sera amené à être modifié par une méthode de ma DLL2.

    J'ai fait mes déclaration de DLL1 dans DLL2 bien comme il faut mais j'ai une erreur à la compile sur cette variable:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    dll_file_output error LNK2001: symbole externe non résolu "public: static bool mux::arret_des_threads" (?arret_des_threads@mux@@2_NA)
    Dans le .h de ma DLL1, ce public bool est déclaré de cette facon:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    #ifdef __DLL__
    	#define IMPEXP __declspec(dllexport)
    #else
    	#define IMPEXP __declspec(dllimport)
    #endif
    ...
    class IMPEXP mux{...
      public :
    	static bool	arret_des_threads;
    };
    Compil OK et .lib et .dll générés

    et dans le .h de DLL2, je code de cette facon:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    #include "Debug\DLL1.h"
    avec le linkage DLL1.lib effectué (.dll et .h bien déplacé dans le bon répertoire).

    Bref, dans la méthode de ma classe DLL2 qui utilise arret_des_threads, j'utilise par exemple cette syntaxe :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    while(! mux::arret_des_threads){... //même pas une modif en fait, juste un test
    Je pense que c'est ici que ca bug car quand j'utilise while(1) au lieu de while(! mux::arret_des_threads), ca compile sans soucis DLL2.

    Merci si quelqu'un a la soluce !

  5. #25
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Points : 15 920
    Points
    15 920
    Par défaut
    Tu as bien défini ta variable statique dans un .cpp ?
    Tu peux aussi passer par une fonction, ce sera peut-être mieux que d'aller bidouiller une variable publique directement, surtout dans ce cas.

  6. #26
    En attente de confirmation mail
    Inscrit en
    Avril 2004
    Messages
    83
    Détails du profil
    Informations forums :
    Inscription : Avril 2004
    Messages : 83
    Points : 54
    Points
    54
    Par défaut
    Dans DLL1.cpp, je définis ma variable de cette façon :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    #include "dll_mux.h"
    bool mux::arret_des_threads;
    ...
    c'est défini correctement je pense.

    Comment ça "passer par une fonction" ?

  7. #27
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Points : 15 920
    Points
    15 920
    Par défaut
    Peut-être qu'il faut remettre un petit IMPEXP devant la définition de ta variable statique.

    Comment ça "passer par une fonction" ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    class IMPEXP mux{
      private :
            static bool arret_des_threads;
     
      public :
    	static void arreter_threads();
    };
     
    void mux::arreter_threads()
    {
        arret_des_threads = true;
    }

  8. #28
    En attente de confirmation mail
    Inscrit en
    Avril 2004
    Messages
    83
    Détails du profil
    Informations forums :
    Inscription : Avril 2004
    Messages : 83
    Points : 54
    Points
    54
    Par défaut
    Citation Envoyé par Laurent Gomila

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    class IMPEXP mux{
      private :
            static bool arret_des_threads;
     
      public :
    	static void arreter_threads();
    };
     
    void mux::arreter_threads()
    {
        arret_des_threads = true;
    }
    ah ok je n'avais pas compris !
    J'essaie tout cela, merci Laurent

  9. #29
    En attente de confirmation mail
    Inscrit en
    Avril 2004
    Messages
    83
    Détails du profil
    Informations forums :
    Inscription : Avril 2004
    Messages : 83
    Points : 54
    Points
    54
    Par défaut
    J'en remet une couche

    J'ai un projet (PROJ.cpp & PROJ.h) qui exploite une DLL (DLL.lib, DLL.dll et DLL.h). Dans PROJ.h, je définie une classe abstraite (classe_abs).
    Dans DLL.h , je déclare une classe concrète (classe_con) qui découle de cette classe abstraite.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    class IMPEXP classe_con : public classe_abs{...}
    (je précise que lors de la création de ma dll , j'ai bien joint au projet la partie de PROJ.h contenant déclaration de classe_abs).

    Dans le main de PROJ.cpp, j'instancie:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     vector <classe_abs *> fee(nb_elem);
    /*puis je fais dans une boucle*/
    fee[i] = new classe_con(...);
    Mon programme compile mais plante lors de l'exécution lorsqu'il arrive sur cette dernière ligne, comme si il ne trouvait pas classe_con alors que j'ai bien linké DLL.lib,créé un include de DLL.h, et déplacé DLL.dll dans le bon repertoire.

    Que de soucis pour maitriser les dll ...

    NB : N'aurais-tu pas un site bien conçu pour bien maitriser les dll en c++ ?

  10. #30
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Points : 15 920
    Points
    15 920
    Par défaut
    Que dit le message d'erreur ? Tu peux essayer de déboguer ? Tu utilises quel environnement de programmation ?

  11. #31
    En attente de confirmation mail
    Inscrit en
    Avril 2004
    Messages
    83
    Détails du profil
    Informations forums :
    Inscription : Avril 2004
    Messages : 83
    Points : 54
    Points
    54
    Par défaut
    Citation Envoyé par Laurent Gomila
    Que dit le message d'erreur ?
    Voici le message d'erreur :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Exception non gérée à 0x7848144b dans exec_multiplexeur.exe:Point d'arrêt utilisateur.
    Citation Envoyé par Laurent Gomila
    Tu peux essayer de déboguer ?
    Niveau debogage je suis allé jusqu'à la ligne pour confirmer que c'est bien fee[i] = new classe_con(...); qui bug.
    Néanmoins , vue que j'avais déjà réalisé ce programme en un seul projet sans DLL (avec des .cpp et .h uniquement) je sais que cette ligne est censée fonctionner.

    Citation Envoyé par Laurent Gomila
    Tu utilises quel environnement de programmation ?
    Je programme sous VS.net 2003 (OS : Win 2000 Pro).

  12. #32
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Points : 15 920
    Points
    15 920
    Par défaut
    Il faudrait débogueur un peu plus en profondeur pour voir ce qui se passe précisément.

  13. #33
    En attente de confirmation mail
    Inscrit en
    Avril 2004
    Messages
    83
    Détails du profil
    Informations forums :
    Inscription : Avril 2004
    Messages : 83
    Points : 54
    Points
    54
    Par défaut
    Je précise pour l'erreur que la flèche verte sous VS indique la ligne
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    _CRTIMP int __cdecl _CrtIsValidHeapPointer(
            const void * pUserData
            )
    {
    ...
    }
    de dbgheap.c ...

  14. #34
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Points : 15 920
    Points
    15 920
    Par défaut
    Et en remontant la pile d'appels ?

  15. #35
    En attente de confirmation mail
    Inscrit en
    Avril 2004
    Messages
    83
    Détails du profil
    Informations forums :
    Inscription : Avril 2004
    Messages : 83
    Points : 54
    Points
    54
    Par défaut
    Pour être encore plus précis, même si je ne comprend pas tout :

    La ligne qui fait bugger quand je rentre en détail dans le prog (Pas a pas détaillé) est celle ci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    #endif  /* _WIN64 */
            {
                return HeapValidate( _crtheap, 0, pHdr(pUserData) );
            }
    qui se trouve dans dbgheap.c


    Ensuite les indications de la pile d'appels sont les suivantes :
    Flèche jaune bloquée sur : ntdll.dll!7848144b();
    Flèche verte bloquée sur : dll.dll ("ca, c'est ma dll qui contient la classe concrete")!_CrtIsValidHeapPointer(const void * pUserData=0x006545c8) Ligne 1807

  16. #36
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Points : 15 920
    Points
    15 920
    Par défaut
    Et en remontant un peu plus y a pas une fonction qui vient de ton code à toi ?

  17. #37
    Expert éminent

    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
    Points : 7 618
    Points
    7 618
    Billets dans le blog
    3
    Par défaut
    En même temps, l'allocation (le new) peut foirer en mode debug parcequ'on a modifié illégalement une autre zone mémoire avant (écriture après la fin d'une chaine, d'un tableau, pointeur non initialisé). En debug, aussi, aucune variable n'est initialisée à 0.

    Pour revenir sur les histoires de DLL...
    A mon avis utiliser un define __DLL__ aussi générique est très dangereux... Quid d'une DLL incluant une autre DLL ? Les deux définissent __DLL__ et pourtant, l'une fait de l'import l'autre de l'export....

    En général j'utilise plutot:
    Dans les headers:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    #ifndef MYLIBRARY_API
      #ifndef MYLIBRARY_LIB
        #define  MYLIBRARY_API   __declspec(dllimport)
      #else
        #define  MYLIBRARY_API
      #endif
    #endif
     
    class MYLIBRARY_API xxxx
    {
    };
    Dans le fichier qui crée le header précompilé:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    #ifdef _USRDLL
    #define MYLIBRARY_API    __declspec(dllexport)
    #else
    #define MYLIBRARY_API
    #endif
    Comme ca, pas de risque que deux dlls se mordent la queue. Pas de risque non plus d'oublier le define... Et surtout, ca gere automatiquement static library, dll, etc...

  18. #38
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 382
    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 382
    Points : 41 590
    Points
    41 590
    Par défaut
    Ce que conseille Visual, c'est de mettre tout dans le header, et le define dans les options du projet de la DLL:
    http://www.developpez.net/forums/sho...42&postcount=6

  19. #39
    Membre du Club
    Profil pro
    Inscrit en
    Février 2007
    Messages
    40
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 40
    Points : 42
    Points
    42
    Par défaut
    Bonjour,

    Mon probleme quoique different a sa place dans cette discussion, c'est pourquoi je la relance.

    Ma dll est en fait un plugin, ce plugin doit comporter une classe qui hérite d'une autre dont toutes les méthodes sont virtuelles. La dll est chargée à l'aide de "LoadLibrary". Dès lors, comment faire pour instancier la classe de la dll ? Suis je obligée d'imposer aux createurs de plugins de fournir dans leur dll une fonction qui instancie leur classe et renvoie un pointeur dessus ou puis je l'instancier moi meme ?

    Merci

  20. #40
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 382
    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 382
    Points : 41 590
    Points
    41 590
    Par défaut
    Tu es obligé de spécifier dans l'interface de la DLL une fonction de création. Cette fonction doit être déclarée extern "C" et toujours être exportée sous le même nom, et c'est ce nom que cherchera ton programme.

    Ou bien, tu peux exiger qu'un fichier de config soit fourni avec le plugin, pour indiquer le nom de la fonction à appeler. Mais dans tous les cas, son prototype doit être fixe, et c'est à toi de l'imposer.

Discussions similaires

  1. Réponses: 2
    Dernier message: 23/05/2013, 03h22
  2. Export d'une classe MFC d'un programme vers DLL
    Par yann458 dans le forum MFC
    Réponses: 1
    Dernier message: 16/05/2013, 11h00
  3. Réponses: 3
    Dernier message: 29/06/2012, 02h09
  4. Dans quel script est la definition d'une classe, d'une fonction,
    Par debutant100 dans le forum Général Python
    Réponses: 6
    Dernier message: 05/04/2011, 20h19
  5. Réponses: 5
    Dernier message: 27/11/2009, 10h21

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