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 :

creer une DLL contenant une classe


Sujet :

C++

  1. #1
    Nouveau membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2013
    Messages
    62
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2013
    Messages : 62
    Points : 30
    Points
    30
    Par défaut creer une DLL contenant une classe
    Bonjour a tous !

    Voilà, je cherche à générer une DLL, en temps normal j'y arrive sauf que cette fois ma DLL doit permettre dexporter une classe c++.

    Méthode utilisée :

    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
     
    // Fichier.h
    #ifndef __MAIN_H__
    #define __MAIN_H__
     
     
     
    #include <iostream>
    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    #include <sstream>
     
     
    class __declspec( dllimport )Fichier
    {
        public:
            Fichier();
            Fichier(std::string i__filePathInput, std::string i__filePathOutput, int codeConversion);
            std::string getFilePathInput();
            std::string getFilePathOutput();
            int getCodeConversion();
            void setFilePathInput(std::string i__filePathInput);
            void setFilePathOutput(std::string i__filePathOutput);
            void setCodeConversion(int codeConversion);
            int openFile(std::string i__filePath, rt_buffer* o__buffer);
            void readImage();
            void writeImage();
        private:
            std::string m__filePathInput;
            std::string m__filePathOutput;
            int m__codeConversion;
    };
     
    #endif // __MAIN_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
    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 "Fichier.h"
    #include <iostream>
    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    #include <sstream>
     
    using namespace std;
     
     
    __declspec( dllexport )Fichier::Fichier()
    {
    }
    __declspec( dllexport )Fichier::Fichier(string i__filePathInput, string i__filePathOutput, int i__codeConversion) : m__filePathInput(i__filePathInput), m__filePathOutput(i__filePathOutput), m__codeConversion(i__codeConversion)
    {
    }
     
    __declspec( dllexport )string Fichier::getFilePathInput()
    {
    }
    __declspec( dllexport )string Fichier::getFilePathOutput()
    {
    }
    __declspec( dllexport )int Fichier::getCodeConversion()
    {
    }
     
    __declspec( dllexport )void Fichier::setFilePathInput(string i__filePathInput)
    {
    }
    __declspec( dllexport )void Fichier::setFilePathOutput(string i__filePathOutput)
    {
    }
    __declspec( dllexport )void Fichier::setCodeConversion(int i__codeConversion)
    {
    }
     
    __declspec( dllexport )int Fichier::openFile(string i__filePath, rt_buffer* o__buffer)
    {
    }
     
    __declspec( dllexport )void Fichier::readImage()
    {
    }
    __declspec( dllexport )void Fichier::writeImage()
    {
    }
    je précise que je link également vers une lib statique que j'utilise pour générer cette DLL


    Ensuite lorsque je veux utiliser cette DLL, je créer un projet console et je link le .lib de ma dll.

    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
     
    #include <iostream>
    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    #include <sstream>
    #include "Fichier.h"
     
    using namespace std;
     
    int main()
    {
        cout << "Hello world!" << endl;
        Fichier l__file1("C:\\image.jpg", "C:\\image2", 3);
     
     
     
        l__file1.convert();
    }
    Et bien je me retrouve face à cette erreure de compilation :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    main.obj : error LNK2019: unresolved external symbol "__declspec(dllimport) public: __thiscall Fichier::~Fichier(void)" (__imp_??1Fichier@@QAE@XZ) referenced in function _main
    bin\Release\useDLL.exe : fatal error LNK1120: 1 unresolved externals
    Merci d'avance a ceux qui pourront bien m'aider

  2. #2
    Membre expérimenté
    Homme Profil pro
    Inscrit en
    Décembre 2010
    Messages
    734
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Décembre 2010
    Messages : 734
    Points : 1 475
    Points
    1 475
    Par défaut
    Il faudrait que dans Fichier.h tu utilises dllimport quand il est inclus dans le client, et dllexport quand il est inclus dans la DLL.
    En général ça se fait avec des #ifdef et un define que tu actives pour compiler la DLL.
    Du style:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    #ifdef MAIN_H_DLL
    #define MAIN_H_DLL_MARK dllexport
    #else
    #define MAIN_H_DLL_MARJ dllimport
    #endif
     
    class __declspec( MAIN_H_DLL_MARK )Fichier{
    Après tu définis (dans les options d'appel du comilo et du linker) MAIN_H_DLL seulement quand tu construis ta DLL.
    Après en ce qui me concerne ce sont certaines fonctions membre que j'ai l'habitude de marquer, pas la classe, mais il faut dire que je veux la compatibilité binaire ce qui engendre plus de contraintes que si tu compiles tout en même temps dans le même environnement.

  3. #3
    Expert confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2012
    Messages
    1 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2012
    Messages : 1 711
    Points : 4 442
    Points
    4 442
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    main.obj : error LNK2019: unresolved external symbol "__declspec(dllimport) public: __thiscall Fichier::~Fichier(void)" (__imp_??1Fichier@@QAE@XZ) referenced in function _main
    bin\Release\useDLL.exe : fatal error LNK1120: 1 unresolved externals
    Le destructeur n'est pas exporté / importé.

  4. #4
    Membre expérimenté
    Homme Profil pro
    Inscrit en
    Décembre 2010
    Messages
    734
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Décembre 2010
    Messages : 734
    Points : 1 475
    Points
    1 475
    Par défaut
    Citation Envoyé par Iradrille Voir le message
    Le destructeur n'est pas exporté / importé.
    Personnellement je n'ai jamais essayé d'importer/exporter des classes, mais seulement des fonctions virtuelles pures membres de classes. Donc je n'osais pas dire que le __dllspec était mal placé, mais je le pensais quand même...
    Il faut si je ne me trompe exporter chaque fonction membre qui doit être visible des clints dans la DLL, et l'importer dans le code client (par ex avec les define que je mentionnais). correct?
    Donc le code de header correct serait:
    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
    // Fichier.h
    #ifndef __MAIN_H__
    #define __MAIN_H__
     
    #include <iostream>
    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    #include <sstream>
     
    #ifdef MAIN_H_DLL
    #define MAIN_H_DLL_MARK dllexport
    #else
    #define MAIN_H_DLL_MARJ dllimport
    #endif
    
    class Fichier
    {
        public:
           __declspec( MAIN_H_DLL_MARK ) Fichier();
           __declspec( MAIN_H_DLL_MARK ) Fichier(std::string i__filePathInput, std::string i__filePathOutput, int codeConversion);
           __declspec( MAIN_H_DLL_MARK ) std::string getFilePathInput();
          __declspec( MAIN_H_DLL_MARK ) std::string getFilePathOutput();
           __declspec( MAIN_H_DLL_MARK ) int getCodeConversion();
           __declspec( MAIN_H_DLL_MARK )  void setFilePathInput(std::string i__filePathInput);
           __declspec( MAIN_H_DLL_MARK ) void setFilePathOutput(std::string i__filePathOutput);
           __declspec( MAIN_H_DLL_MARK ) void setCodeConversion(int codeConversion);
           __declspec( MAIN_H_DLL_MARK ) int openFile(std::string i__filePath, rt_buffer* o__buffer);
           __declspec( MAIN_H_DLL_MARK ) void readImage();
           __declspec( MAIN_H_DLL_MARK ) void writeImage();
        private:
            std::string m__filePathInput;
            std::string m__filePathOutput;
            int m__codeConversion;
    };
     
    #endif // __MAIN_H__

  5. #5
    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
    Je me demande si tout ça n'est pas automatique quand une classe est déclarée dllexport.

    Le problème, c'est que le destructeur est automatiquement généré par le compilo, et que ça semble entrer en conflit avec le fait de faire une DLL.
    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.

  6. #6
    Membre expérimenté
    Homme Profil pro
    Inscrit en
    Décembre 2010
    Messages
    734
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Décembre 2010
    Messages : 734
    Points : 1 475
    Points
    1 475
    Par défaut
    Alors ne faut-il pas le déclarer explicitement? Vide en C++ pré-11, et defaulten c++11?

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

    Informations professionnelles :
    Activité : aucun

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

    Personnellement, je préfères utiliser les directives préprocesseurs sous la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    #ifdef _WIN32
        #ifdef SHARED
            #ifdef BUILD_MY_MODULE
                #define MYMODULE_API __declespec(dllexport)
            #else
                #define MYMODULE_API __declspec(dllimport)
            #endif
        #else
            #define MYMODULE_API
        #endif
    #else
        #define MYMODULE_API
    #endif
    car, outre __declspec(dllimport) et __ceclspec(dllexport), il y a d'autre conventions d'appel possible, que l'on peut parfaitement laisser par défaut sous linux ou lorsque l'on crée une bibliothèque statique (et il semble que tu veuilles les deux, non )

    Cela sous entend qu'il faut définir SHARED pour indiquer que l'on veut travailler (compilation et utilisation) avec une dll et BUILD_MY_MODULE (nom à adapter en fonction du nom du module ) lors de la compilation de la dll, mais cela permet une plus grande souplesse.

    Ceci dit, à partir du moment où ta classe est déclarée __declspec(dllexport/dllimport), tu n'as plus besoin de t'inquiéter pour les autres fonctions, ni pour leur implémentation, d'ailleurs:
    MyClass.h
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    class MYMODULE_API MyClass{
        public:
            void foo();
    };
    MyClass.cpp
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    void MyClass::foo(){
        /* ... */
    };
    fonctionnera parfaitement
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

Discussions similaires

  1. Réponses: 12
    Dernier message: 08/07/2015, 15h08
  2. Réponses: 3
    Dernier message: 06/03/2013, 13h00
  3. Réponses: 6
    Dernier message: 10/06/2010, 15h31
  4. [VBA Excel] Appliquer une macro sur une celulle contenant une valeur
    Par tchauviere dans le forum Macros et VBA Excel
    Réponses: 7
    Dernier message: 21/01/2008, 10h21
  5. utiliser une dll dans une dll
    Par anthonycosson dans le forum MFC
    Réponses: 2
    Dernier message: 09/05/2006, 21h42

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