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 c++ export de classe


Sujet :

C++

  1. #1
    Futur Membre du Club
    Inscrit en
    Juillet 2002
    Messages
    21
    Détails du profil
    Informations forums :
    Inscription : Juillet 2002
    Messages : 21
    Points : 8
    Points
    8
    Par défaut DLL c++ export de classe
    Bonjour,

    Cela fait quelques jours que je cherche le moyen d'exporter une classe c++ contenant seulement de la donnée (chaines de caractères, entiers...) dans une dll.

    Quelques contraintes, parce que sinon, ça serait trop facile :
    - La dll doit être utilisable par du delphi, du vb, ... donc me dites pas d'importer le .h dans l'appli qui utilise la dll, c'est pas possible.
    - L'objet que je veux exporter contient d'autres objets (que je vais devoir exporter aussi)

    Ou j'en suis aujourd'hui :
    - J'ai vu qu'on pouvait faire du __declspec(dllexport) mais je dois avoir le .h pour utiliser ma classe -> je veux juste une dll
    - J'ai essayé avec un .def (créé à partir d'infos trouvées dans le .map) mais j'ai l'impression que les classes n'y sont pas. J'ai le constructeur, le destructeur mais pas la classe en elle même. Ou alors je n'ai pas compris comment l'importer après.
    - Voilà le code simplifié :

    [DLL]
    Ma classe de donné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
    #undef AFX_DATA
    #define AFX_DATA AFX_EXT_DATA
     
    #include <string>
     
    class Plop
    {
    public:
    	Plop(void);
    	~Plop(void);
     
    public:
    	std::string* plopy;
    };
     
    #undef AFX_DATA
    #define AFX_DATA
    une fonction (que j'exporte également) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    Plop* GiveMePlop()
    {
    	return new Plop();
    }
    Mon fichier .def :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    LIBRARY      "PlopAPI"
     
    EXPORTS
    	GiveMePlop @1
    	Plop = ??0Plop@@QAE@XZ @2
    [APPLI]
    ma classe qui utilise la dll :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    typedef int (*GiveMePlopFunc)(); /* je voudrais pas du int mais du Plop* */
    HINSTANCE hInstLibrary = LoadLibrary(_T("Plop.dll"));
    if (hInstLibrary)
    {
    	GiveMePlopFunc plopFunc = (GiveMePlopFunc)GetProcAddress(hInstLibrary,"GiveMePlop");
    	/* ici je voudrais récupérer mon objet plop : Plop* plop = */ plopFunc();
    }
    J'ai l'impression qu'il manque pas grand chose pour que ca marche ou bien que c'est impossible mais dans les deux cas, je veux bien savoir comment faire.

    Merci d'avance

  2. #2
    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
    Tu dois passer par une classe abstraite sans données, contenant seulement des fonctions virtuelles pures.
    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    //IPlop.h (doit être inclus par le code utilisateur)
    class IPlop
    {
    public:
    	int getplopx() const = 0;
    };
     
    typedef IPlop * (__stdcall * GIVEMEPLOPPROC)(void);
    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    //MyPlop.h (header de la DLL uniquement, le code utilisateur ne le connait pas)
     
    #include "IPlop.h"
     
    class MyPlop : public IPlop
    {
    public:
    	MyPlop();
    	~MyPlop(void);
    	int getplopx() const;
    private:
    	int plopx;
    };
    Code C++ : 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
    //MyPlop.cpp
     
    #include "MyPlop.h"
     
    MyPlop::MyPlop()
     : plopx(42)
    {
    }
    MyPlop::~MyPlop(void)
    {
    }
     
    int MyPlop::getplopx() const
    {
    	return plopx;
    }
     
    extern "C" IPlop* __stdcall GiveMePlop(void)
    {
    	IPlop *ret = new MyPlop();
    	return ret;
    }
    Les strings, je ne suis pas sûr qu'elles passent. Par contre, des tableaux de char passeront à coup sûr.
    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.

  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
    Ou mieux, tu fais carrément un objet COM:
    Code C/C++ : 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
    /* IPlop.h */
     
    DECLARE_INTERFACE_(IPlop, IUnknown)
    {
    	/* IUnknown */
    	STDMETHOD(QueryInterface)(REFIID, void**) PURE;
    	STDMETHOD_(ULONG, AddRef)(void) PURE;
    	STDMETHOD_(ULONG, Release)(void) PURE;
     
    	/* IPlop */
    	STDMETHOD(get_plopx)(int *ret) PURE;
    	STDMETHOD(get_plopy)(BSTR *ret) PURE;
    };
     
    // {9D30A9BA-CFA4-4736-A093-9FE81CC1BCC2}
    DEFINE_GUID(IID_IPlop, 
    0x9d30a9ba, 0xcfa4, 0x4736, 0xa0, 0x93, 0x9f, 0xe8, 0x1c, 0xc1, 0xbc, 0xc2);
    Code C++ : 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
    // MyPlop.cpp
     
    #include "IPlop.h"
    #include <string>
     
    //Implémentation simple: Objet à une seule interface, non-agrégable.
    //Pas de factory : Juste une fonction de création
    class MyPlop : public IPlop
    {
    public:
    	/* IUnknown */
    	STDMETHODIMP QueryInterface(REFIID, void**);
    	STDMETHODIMP_(ULONG) AddRef(void)
    	{
    		return InterlockedIncrement(&cRefs);
    	}
    	STDMETHODIMP_(ULONG) Release(void)
    	{
    		ULONG ret = InterlockedDecrement(&cRefs);
    		if(cRefs == 0)
    		{
    			cRefs = 42; // http://blogs.msdn.com/oldnewthing/archive/2005/09/28/474855.aspx
    			delete this;
    		}
    		return ret;
    	}
     
    	/* IPlop */
    	STDMETHODIMP get_plopx(int *ret);
    	STDMETHODIMP get_plopy(BSTR *ret);
     
    	/* Le reste */
    	MyPlop(void);
    	~MyPlop(void);
    private:
    	LONG cRefs;
    	int plopx;
    	std::wstring plopy;
    };
    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
    //MyPlop.cpp
     
    #include <windows.h>
    #include "MyPlop.h"
    #include <cassert>
     
    MyPlop::MyPlop(void)
     cRefs(1), plopx(10), plopy(L"Coucou")
    {
    }
     
    MyPlop::~MyPlop(void)
    {
    	assert(cRefs==42);
    }
     
    STDMETHODIMP MyPlop::QueryInterface(REFIID riid, void **ppv)
    {
    	HRESULT hr = S_OK;
    	if(riid==IID_IUnknown)
    	{
    		IUnknown *pIface = this;
    		*ppv = pIface;
    	}
    	else if(riid==IID_IPlop)
    	{
    		IPlop *pIface = this;
    		*ppv = pIface;
    	}
    	else
    	{
    		hr = E_NOINTERFACE;
    		*ppv = NULL;
    	}
     
    	if(*ppv != NULL)
    		static_cast<IUnknown*>(*ppv)->AddRef();
    	return hr;
    }
     
    STDMETHODIMP MyPlop::get_plopx(int *ret)
    {
    	*ret = plopx;
    	return S_OK;
    }
     
    STDMETHODIMP MyPlop::get_plopy(BSTR *ret)
    {
    	*ret = SysAllocString(plopy.c_str());
    	if(*ret==NULL)
    		return E_OUTOFMEMORY;
    	return S_OK;
    }
     
    extern "C" IPlop * __stdcall GiveMePlop(void)
    {
    	IPlop * ret = new Plop();
    	return ret;
    }
    (j'ai écris ça de tête, je ne sais pas si ça compile. J'espère que je n'ai pas trop perdu la main...)


    ...ou encore mieux, tu peux faire carrément un composant COM, mais là ce serait vraiment exagéré.
    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.

Discussions similaires

  1. Réponses: 4
    Dernier message: 31/05/2009, 10h38
  2. Exporter une classe dans une DLL
    Par mayayu dans le forum C++
    Réponses: 3
    Dernier message: 29/12/2008, 11h53
  3. Exporter une class dans une DLL
    Par squale69 dans le forum C++
    Réponses: 2
    Dernier message: 25/04/2008, 17h54
  4. Réponses: 6
    Dernier message: 29/03/2008, 19h01
  5. Réponses: 9
    Dernier message: 27/04/2004, 11h01

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