Bonjour,
Je cherche une méthode pour rendre une DLL de classe chargeable
dynamiquement.
J'ai trouvé pas mal d'information sur le net mais rien ne semble
vouloir fonctionner. Il me semble avoir compris que cela dépendait du
compilateur, la méthode semble varier entre VC++ 4 et VC++ 5. De même,
elle semble différente avec les compilateurs de chez Borland.
Moi, je travaille avec un VC++ 6.
Le problème se situe à l'édition des liens puisque les méthodes de la
classe ne peuvent, évidement, pas être résolu.
Quels sont les modifications à apporter pour que l'édition des liens
se passe bien ?
Bonjour,
Je cherche une méthode pour rendre une DLL de classe chargeable
dynamiquement.
J'ai trouvé pas mal d'information sur le net mais rien ne semble
vouloir fonctionner. Il me semble avoir compris que cela dépendait du
compilateur, la méthode semble varier entre VC++ 4 et VC++ 5. De même,
elle semble différente avec les compilateurs de chez Borland.
Moi, je travaille avec un VC++ 6.
Le problème se situe à l'édition des liens puisque les méthodes de la
classe ne peuvent, évidement, pas être résolu.
Quels sont les modifications à apporter pour que l'édition des liens
se passe bien ?
Bonjour,
Je cherche une méthode pour rendre une DLL de classe chargeable
dynamiquement.
J'ai trouvé pas mal d'information sur le net mais rien ne semble
vouloir fonctionner. Il me semble avoir compris que cela dépendait du
compilateur, la méthode semble varier entre VC++ 4 et VC++ 5. De même,
elle semble différente avec les compilateurs de chez Borland.
Moi, je travaille avec un VC++ 6.
Le problème se situe à l'édition des liens puisque les méthodes de la
classe ne peuvent, évidement, pas être résolu.
Quels sont les modifications à apporter pour que l'édition des liens
se passe bien ?
smu wrote:Bonjour,
Je cherche une méthode pour rendre une DLL de classe chargeable
dynamiquement.
J'ai trouvé pas mal d'information sur le net mais rien ne semble
vouloir fonctionner. Il me semble avoir compris que cela dépendait du
compilateur, la méthode semble varier entre VC++ 4 et VC++ 5. De même,
elle semble différente avec les compilateurs de chez Borland.
Oui, c'est dépendant du compilo à cause du name mangling...Moi, je travaille avec un VC++ 6.
VC4 à 6... c'est un peu ordinausoresque tout çà... On est à VC 7.1
aujourd'hui! (dont une version gratuite est téléchargeable...)Le problème se situe à l'édition des liens puisque les méthodes de la
classe ne peuvent, évidement, pas être résolu.
Quels sont les modifications à apporter pour que l'édition des liens
se passe bien ?
Il n'y a pas de solution miracle. La méthode habituellement utilisée, c'est
de n'exporter de la DLL qu'une méthode factory déclarée extern "C", mais
c'est déjà ce que tu fais donc tout va bien. Quel est le problème exactement
(message d'erreur?). Utilises depends pour vérifier ce qui est effectivement
exporté de la DLL.
Arnaud
smu wrote:
Bonjour,
Je cherche une méthode pour rendre une DLL de classe chargeable
dynamiquement.
J'ai trouvé pas mal d'information sur le net mais rien ne semble
vouloir fonctionner. Il me semble avoir compris que cela dépendait du
compilateur, la méthode semble varier entre VC++ 4 et VC++ 5. De même,
elle semble différente avec les compilateurs de chez Borland.
Oui, c'est dépendant du compilo à cause du name mangling...
Moi, je travaille avec un VC++ 6.
VC4 à 6... c'est un peu ordinausoresque tout çà... On est à VC 7.1
aujourd'hui! (dont une version gratuite est téléchargeable...)
Le problème se situe à l'édition des liens puisque les méthodes de la
classe ne peuvent, évidement, pas être résolu.
Quels sont les modifications à apporter pour que l'édition des liens
se passe bien ?
Il n'y a pas de solution miracle. La méthode habituellement utilisée, c'est
de n'exporter de la DLL qu'une méthode factory déclarée extern "C", mais
c'est déjà ce que tu fais donc tout va bien. Quel est le problème exactement
(message d'erreur?). Utilises depends pour vérifier ce qui est effectivement
exporté de la DLL.
Arnaud
smu wrote:Bonjour,
Je cherche une méthode pour rendre une DLL de classe chargeable
dynamiquement.
J'ai trouvé pas mal d'information sur le net mais rien ne semble
vouloir fonctionner. Il me semble avoir compris que cela dépendait du
compilateur, la méthode semble varier entre VC++ 4 et VC++ 5. De même,
elle semble différente avec les compilateurs de chez Borland.
Oui, c'est dépendant du compilo à cause du name mangling...Moi, je travaille avec un VC++ 6.
VC4 à 6... c'est un peu ordinausoresque tout çà... On est à VC 7.1
aujourd'hui! (dont une version gratuite est téléchargeable...)Le problème se situe à l'édition des liens puisque les méthodes de la
classe ne peuvent, évidement, pas être résolu.
Quels sont les modifications à apporter pour que l'édition des liens
se passe bien ?
Il n'y a pas de solution miracle. La méthode habituellement utilisée, c'est
de n'exporter de la DLL qu'une méthode factory déclarée extern "C", mais
c'est déjà ce que tu fais donc tout va bien. Quel est le problème exactement
(message d'erreur?). Utilises depends pour vérifier ce qui est effectivement
exporté de la DLL.
Arnaud
Bonjour,
Je cherche une méthode pour rendre une DLL de classe chargeable
dynamiquement.
J'ai trouvé pas mal d'information sur le net mais rien ne semble vouloir
fonctionner. Il me semble avoir compris que cela dépendait du compilateur,
la méthode semble varier entre VC++ 4 et VC++ 5. De même, elle semble
différente avec les compilateurs de chez Borland.
Moi, je travaille avec un VC++ 6.
Le problème se situe à l'édition des liens puisque les méthodes de la
classe ne peuvent, évidement, pas être résolu.
Quels sont les modifications à apporter pour que l'édition des liens se
passe bien ?
Je vous fournis les sources existants à ce jour.
D'avance merci.
smu
Voici les sources de la DLL :
------------ myClass.h ------------
#ifndef MY_CLASS_HEADER__
#define MY_CLASS_HEADER__
#ifdef DLLCLASS_EXPORTS
#define IMPEXP __declspec(dllexport)
#else
#define IMPEXP __declspec(dllimport)
#endif /* DLLCLASS_EXPORTS */
class IMPEXP myClass
{
public:
myClass(void);
~myClass(void);
void set(int local);
int get(void);
private:
int number;
bool initialized;
};
extern "C" IMPEXP myClass * myClass_createInstance(void);
typedef myClass * (* myClass_createInstancePTR)(void);
#endif /* MY_CLASS_HEADER__ */
------------ myClass.cpp ------------
#include "myClass.h"
#include <iostream>
myClass::myClass(void)
{
std::cout << "Initialization" << std::endl;
initialized = false;
number = 0;
}
myClass::~myClass(void)
{
std::cout << "Destruction" << std::endl;
}
void myClass::set(int local)
{
initialized = true;
number = local;
}
int myClass::get(void)
{
if (!initialized)
{
throw -1;
}
return number;
}
myClass * myClass_createInstance(void)
{
return new myClass;
}
------------ DLLClass.cpp ------------
#include <windows.h>
BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved)
{
return TRUE;
}
Et voici les sources de l'application de test :
------------ DLLClassEXEDynamically.cpp ------------
#include "../DLLClass/myClass.h"
#include <stdlib.h>
#include <iostream>
#include <windows.h>
int main(int argc, char * argv[])
{
HMODULE hDLL;
myClass * check = NULL;
myClass_createInstancePTR myClass_createInstance = NULL;
hDLL = LoadLibrary("../DLLClass/Debug/DLLClass.dll");
if (NULL == hDLL)
{
std::cout << "Could not load the DLL" << std::endl;
return EXIT_FAILURE;
}
myClass_createInstance = (myClass_createInstancePTR)GetProcAddress(hDLL,
"myClass_createInstance");
std::cout << "Trying to create a new instance of the class" <<
std::endl;
check = myClass_createInstance();
try
{
std::cout << "The class contains: " << check->get() << std::endl;
}
catch(int)
{
std::cout << "An exception throwed" << std::endl;
}
check->set(5);
try
{
std::cout << "The class contains: " << check->get() << std::endl;
}
catch(int)
{
std::cout << "An exception throwed" << std::endl;
}
std::cout << "Trying to delete the instance of the class" << std::endl;
delete check;
FreeLibrary(hDLL);
return EXIT_SUCCESS;
}
Bonjour,
Je cherche une méthode pour rendre une DLL de classe chargeable
dynamiquement.
J'ai trouvé pas mal d'information sur le net mais rien ne semble vouloir
fonctionner. Il me semble avoir compris que cela dépendait du compilateur,
la méthode semble varier entre VC++ 4 et VC++ 5. De même, elle semble
différente avec les compilateurs de chez Borland.
Moi, je travaille avec un VC++ 6.
Le problème se situe à l'édition des liens puisque les méthodes de la
classe ne peuvent, évidement, pas être résolu.
Quels sont les modifications à apporter pour que l'édition des liens se
passe bien ?
Je vous fournis les sources existants à ce jour.
D'avance merci.
smu
Voici les sources de la DLL :
------------ myClass.h ------------
#ifndef MY_CLASS_HEADER__
#define MY_CLASS_HEADER__
#ifdef DLLCLASS_EXPORTS
#define IMPEXP __declspec(dllexport)
#else
#define IMPEXP __declspec(dllimport)
#endif /* DLLCLASS_EXPORTS */
class IMPEXP myClass
{
public:
myClass(void);
~myClass(void);
void set(int local);
int get(void);
private:
int number;
bool initialized;
};
extern "C" IMPEXP myClass * myClass_createInstance(void);
typedef myClass * (* myClass_createInstancePTR)(void);
#endif /* MY_CLASS_HEADER__ */
------------ myClass.cpp ------------
#include "myClass.h"
#include <iostream>
myClass::myClass(void)
{
std::cout << "Initialization" << std::endl;
initialized = false;
number = 0;
}
myClass::~myClass(void)
{
std::cout << "Destruction" << std::endl;
}
void myClass::set(int local)
{
initialized = true;
number = local;
}
int myClass::get(void)
{
if (!initialized)
{
throw -1;
}
return number;
}
myClass * myClass_createInstance(void)
{
return new myClass;
}
------------ DLLClass.cpp ------------
#include <windows.h>
BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved)
{
return TRUE;
}
Et voici les sources de l'application de test :
------------ DLLClassEXEDynamically.cpp ------------
#include "../DLLClass/myClass.h"
#include <stdlib.h>
#include <iostream>
#include <windows.h>
int main(int argc, char * argv[])
{
HMODULE hDLL;
myClass * check = NULL;
myClass_createInstancePTR myClass_createInstance = NULL;
hDLL = LoadLibrary("../DLLClass/Debug/DLLClass.dll");
if (NULL == hDLL)
{
std::cout << "Could not load the DLL" << std::endl;
return EXIT_FAILURE;
}
myClass_createInstance = (myClass_createInstancePTR)GetProcAddress(hDLL,
"myClass_createInstance");
std::cout << "Trying to create a new instance of the class" <<
std::endl;
check = myClass_createInstance();
try
{
std::cout << "The class contains: " << check->get() << std::endl;
}
catch(int)
{
std::cout << "An exception throwed" << std::endl;
}
check->set(5);
try
{
std::cout << "The class contains: " << check->get() << std::endl;
}
catch(int)
{
std::cout << "An exception throwed" << std::endl;
}
std::cout << "Trying to delete the instance of the class" << std::endl;
delete check;
FreeLibrary(hDLL);
return EXIT_SUCCESS;
}
Bonjour,
Je cherche une méthode pour rendre une DLL de classe chargeable
dynamiquement.
J'ai trouvé pas mal d'information sur le net mais rien ne semble vouloir
fonctionner. Il me semble avoir compris que cela dépendait du compilateur,
la méthode semble varier entre VC++ 4 et VC++ 5. De même, elle semble
différente avec les compilateurs de chez Borland.
Moi, je travaille avec un VC++ 6.
Le problème se situe à l'édition des liens puisque les méthodes de la
classe ne peuvent, évidement, pas être résolu.
Quels sont les modifications à apporter pour que l'édition des liens se
passe bien ?
Je vous fournis les sources existants à ce jour.
D'avance merci.
smu
Voici les sources de la DLL :
------------ myClass.h ------------
#ifndef MY_CLASS_HEADER__
#define MY_CLASS_HEADER__
#ifdef DLLCLASS_EXPORTS
#define IMPEXP __declspec(dllexport)
#else
#define IMPEXP __declspec(dllimport)
#endif /* DLLCLASS_EXPORTS */
class IMPEXP myClass
{
public:
myClass(void);
~myClass(void);
void set(int local);
int get(void);
private:
int number;
bool initialized;
};
extern "C" IMPEXP myClass * myClass_createInstance(void);
typedef myClass * (* myClass_createInstancePTR)(void);
#endif /* MY_CLASS_HEADER__ */
------------ myClass.cpp ------------
#include "myClass.h"
#include <iostream>
myClass::myClass(void)
{
std::cout << "Initialization" << std::endl;
initialized = false;
number = 0;
}
myClass::~myClass(void)
{
std::cout << "Destruction" << std::endl;
}
void myClass::set(int local)
{
initialized = true;
number = local;
}
int myClass::get(void)
{
if (!initialized)
{
throw -1;
}
return number;
}
myClass * myClass_createInstance(void)
{
return new myClass;
}
------------ DLLClass.cpp ------------
#include <windows.h>
BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved)
{
return TRUE;
}
Et voici les sources de l'application de test :
------------ DLLClassEXEDynamically.cpp ------------
#include "../DLLClass/myClass.h"
#include <stdlib.h>
#include <iostream>
#include <windows.h>
int main(int argc, char * argv[])
{
HMODULE hDLL;
myClass * check = NULL;
myClass_createInstancePTR myClass_createInstance = NULL;
hDLL = LoadLibrary("../DLLClass/Debug/DLLClass.dll");
if (NULL == hDLL)
{
std::cout << "Could not load the DLL" << std::endl;
return EXIT_FAILURE;
}
myClass_createInstance = (myClass_createInstancePTR)GetProcAddress(hDLL,
"myClass_createInstance");
std::cout << "Trying to create a new instance of the class" <<
std::endl;
check = myClass_createInstance();
try
{
std::cout << "The class contains: " << check->get() << std::endl;
}
catch(int)
{
std::cout << "An exception throwed" << std::endl;
}
check->set(5);
try
{
std::cout << "The class contains: " << check->get() << std::endl;
}
catch(int)
{
std::cout << "An exception throwed" << std::endl;
}
std::cout << "Trying to delete the instance of the class" << std::endl;
delete check;
FreeLibrary(hDLL);
return EXIT_SUCCESS;
}
"smu" wrote in message
news:4221aec1$0$4071$Bonjour,
Je cherche une méthode pour rendre une DLL de classe chargeable
dynamiquement.
J'ai trouvé pas mal d'information sur le net mais rien ne semble vouloir
fonctionner. Il me semble avoir compris que cela dépendait du compilateur,
la méthode semble varier entre VC++ 4 et VC++ 5. De même, elle semble
différente avec les compilateurs de chez Borland.
Moi, je travaille avec un VC++ 6.
Le problème se situe à l'édition des liens puisque les méthodes de la
classe ne peuvent, évidement, pas être résolu.
Quels sont les modifications à apporter pour que l'édition des liens se
passe bien ?
Je vous fournis les sources existants à ce jour.
D'avance merci.
smu
Voici les sources de la DLL :
------------ myClass.h ------------
#ifndef MY_CLASS_HEADER__
#define MY_CLASS_HEADER__
#ifdef DLLCLASS_EXPORTS
#define IMPEXP __declspec(dllexport)
#else
#define IMPEXP __declspec(dllimport)
#endif /* DLLCLASS_EXPORTS */
class IMPEXP myClass
{
public:
myClass(void);
~myClass(void);
void set(int local);
int get(void);
private:
int number;
bool initialized;
};
extern "C" IMPEXP myClass * myClass_createInstance(void);
typedef myClass * (* myClass_createInstancePTR)(void);
#endif /* MY_CLASS_HEADER__ */
------------ myClass.cpp ------------
#include "myClass.h"
#include <iostream>
myClass::myClass(void)
{
std::cout << "Initialization" << std::endl;
initialized = false;
number = 0;
}
myClass::~myClass(void)
{
std::cout << "Destruction" << std::endl;
}
void myClass::set(int local)
{
initialized = true;
number = local;
}
int myClass::get(void)
{
if (!initialized)
{
throw -1;
}
return number;
}
myClass * myClass_createInstance(void)
{
return new myClass;
}
------------ DLLClass.cpp ------------
#include <windows.h>
BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved)
{
return TRUE;
}
Et voici les sources de l'application de test :
------------ DLLClassEXEDynamically.cpp ------------
#include "../DLLClass/myClass.h"
#include <stdlib.h>
#include <iostream>
#include <windows.h>
int main(int argc, char * argv[])
{
HMODULE hDLL;
myClass * check = NULL;
myClass_createInstancePTR myClass_createInstance = NULL;
hDLL = LoadLibrary("../DLLClass/Debug/DLLClass.dll");
if (NULL == hDLL)
{
std::cout << "Could not load the DLL" << std::endl;
return EXIT_FAILURE;
}
myClass_createInstance = (myClass_createInstancePTR)GetProcAddress(hDLL,
"myClass_createInstance");
std::cout << "Trying to create a new instance of the class" <<
std::endl;
check = myClass_createInstance();
try
{
std::cout << "The class contains: " << check->get() << std::endl;
}
catch(int)
{
std::cout << "An exception throwed" << std::endl;
}
check->set(5);
try
{
std::cout << "The class contains: " << check->get() << std::endl;
}
catch(int)
{
std::cout << "An exception throwed" << std::endl;
}
std::cout << "Trying to delete the instance of the class" << std::endl;
delete check;
FreeLibrary(hDLL);
return EXIT_SUCCESS;
}
La solution est d'utiliser des méthodes virtuelles. En effet, les fonctions
virtulles n'ont pas besoin d'être exportées, car on y accède par la
"v-table" de l'objet.
Utiliser des méthodes virtuelles permet aussi de séparer complètement
l'interface d'accès à la classe dans la DLL et son implémentation,
permettant facilement de changer le contenue de la DLL sans changer, ni même
recompiler l'exécutable tant que l'interface reste identique.
Note that only the factory fonction needs to be exported using
__declspec(dllexport). The class does not.
------- myClass.h -------
class myClass
{
public:
virtual ~myClass() {}
virtual void set(int value) = 0;
virtual int get() = 0;
};
extern "C" typedef myClass* (*myClass_createInstancePTR)();
------- myClassDLL.cpp ------
#include "myClass.h"
class myClassDll : public myClass
{
myClassDll();
virtual ~myClassDll();
virtual void set(int value);
virtual int get();
int number;
boolean initialized;
};
myClassDll::myClassDll()
{ ... }
myClassDll::~myClassDll()
{ ... }
void myClassDll::set(int value)
{ ... }
int myClassDll:get()
{ ... }
extern "C" __declspec(dllexport) myClass* myClass_createInstance()
{
return new myClassDll();
}
---- main.cpp ----
#include "myClass.h"
#include <windows.h>
int main()
{
hDLL = LoadLibrary("../DLLClass/Debug/DLLClass.dll");
myClass_createInstancePTR createInstance = (myClass_createInstancePTR)
GetProcAddress(hDLL, "myClass_createInstance");
myClass* instance = myClass_createInstance();
instance->set(5);
std::cout << "The class contains: " << instance->get() << std::endl;
delete instance;
FreeLibrary(hDLL);
return 0;
}
"smu" <pas@d.adresse> wrote in message
news:4221aec1$0$4071$636a15ce@news.free.fr...
Bonjour,
Je cherche une méthode pour rendre une DLL de classe chargeable
dynamiquement.
J'ai trouvé pas mal d'information sur le net mais rien ne semble vouloir
fonctionner. Il me semble avoir compris que cela dépendait du compilateur,
la méthode semble varier entre VC++ 4 et VC++ 5. De même, elle semble
différente avec les compilateurs de chez Borland.
Moi, je travaille avec un VC++ 6.
Le problème se situe à l'édition des liens puisque les méthodes de la
classe ne peuvent, évidement, pas être résolu.
Quels sont les modifications à apporter pour que l'édition des liens se
passe bien ?
Je vous fournis les sources existants à ce jour.
D'avance merci.
smu
Voici les sources de la DLL :
------------ myClass.h ------------
#ifndef MY_CLASS_HEADER__
#define MY_CLASS_HEADER__
#ifdef DLLCLASS_EXPORTS
#define IMPEXP __declspec(dllexport)
#else
#define IMPEXP __declspec(dllimport)
#endif /* DLLCLASS_EXPORTS */
class IMPEXP myClass
{
public:
myClass(void);
~myClass(void);
void set(int local);
int get(void);
private:
int number;
bool initialized;
};
extern "C" IMPEXP myClass * myClass_createInstance(void);
typedef myClass * (* myClass_createInstancePTR)(void);
#endif /* MY_CLASS_HEADER__ */
------------ myClass.cpp ------------
#include "myClass.h"
#include <iostream>
myClass::myClass(void)
{
std::cout << "Initialization" << std::endl;
initialized = false;
number = 0;
}
myClass::~myClass(void)
{
std::cout << "Destruction" << std::endl;
}
void myClass::set(int local)
{
initialized = true;
number = local;
}
int myClass::get(void)
{
if (!initialized)
{
throw -1;
}
return number;
}
myClass * myClass_createInstance(void)
{
return new myClass;
}
------------ DLLClass.cpp ------------
#include <windows.h>
BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved)
{
return TRUE;
}
Et voici les sources de l'application de test :
------------ DLLClassEXEDynamically.cpp ------------
#include "../DLLClass/myClass.h"
#include <stdlib.h>
#include <iostream>
#include <windows.h>
int main(int argc, char * argv[])
{
HMODULE hDLL;
myClass * check = NULL;
myClass_createInstancePTR myClass_createInstance = NULL;
hDLL = LoadLibrary("../DLLClass/Debug/DLLClass.dll");
if (NULL == hDLL)
{
std::cout << "Could not load the DLL" << std::endl;
return EXIT_FAILURE;
}
myClass_createInstance = (myClass_createInstancePTR)GetProcAddress(hDLL,
"myClass_createInstance");
std::cout << "Trying to create a new instance of the class" <<
std::endl;
check = myClass_createInstance();
try
{
std::cout << "The class contains: " << check->get() << std::endl;
}
catch(int)
{
std::cout << "An exception throwed" << std::endl;
}
check->set(5);
try
{
std::cout << "The class contains: " << check->get() << std::endl;
}
catch(int)
{
std::cout << "An exception throwed" << std::endl;
}
std::cout << "Trying to delete the instance of the class" << std::endl;
delete check;
FreeLibrary(hDLL);
return EXIT_SUCCESS;
}
La solution est d'utiliser des méthodes virtuelles. En effet, les fonctions
virtulles n'ont pas besoin d'être exportées, car on y accède par la
"v-table" de l'objet.
Utiliser des méthodes virtuelles permet aussi de séparer complètement
l'interface d'accès à la classe dans la DLL et son implémentation,
permettant facilement de changer le contenue de la DLL sans changer, ni même
recompiler l'exécutable tant que l'interface reste identique.
Note that only the factory fonction needs to be exported using
__declspec(dllexport). The class does not.
------- myClass.h -------
class myClass
{
public:
virtual ~myClass() {}
virtual void set(int value) = 0;
virtual int get() = 0;
};
extern "C" typedef myClass* (*myClass_createInstancePTR)();
------- myClassDLL.cpp ------
#include "myClass.h"
class myClassDll : public myClass
{
myClassDll();
virtual ~myClassDll();
virtual void set(int value);
virtual int get();
int number;
boolean initialized;
};
myClassDll::myClassDll()
{ ... }
myClassDll::~myClassDll()
{ ... }
void myClassDll::set(int value)
{ ... }
int myClassDll:get()
{ ... }
extern "C" __declspec(dllexport) myClass* myClass_createInstance()
{
return new myClassDll();
}
---- main.cpp ----
#include "myClass.h"
#include <windows.h>
int main()
{
hDLL = LoadLibrary("../DLLClass/Debug/DLLClass.dll");
myClass_createInstancePTR createInstance = (myClass_createInstancePTR)
GetProcAddress(hDLL, "myClass_createInstance");
myClass* instance = myClass_createInstance();
instance->set(5);
std::cout << "The class contains: " << instance->get() << std::endl;
delete instance;
FreeLibrary(hDLL);
return 0;
}
"smu" wrote in message
news:4221aec1$0$4071$Bonjour,
Je cherche une méthode pour rendre une DLL de classe chargeable
dynamiquement.
J'ai trouvé pas mal d'information sur le net mais rien ne semble vouloir
fonctionner. Il me semble avoir compris que cela dépendait du compilateur,
la méthode semble varier entre VC++ 4 et VC++ 5. De même, elle semble
différente avec les compilateurs de chez Borland.
Moi, je travaille avec un VC++ 6.
Le problème se situe à l'édition des liens puisque les méthodes de la
classe ne peuvent, évidement, pas être résolu.
Quels sont les modifications à apporter pour que l'édition des liens se
passe bien ?
Je vous fournis les sources existants à ce jour.
D'avance merci.
smu
Voici les sources de la DLL :
------------ myClass.h ------------
#ifndef MY_CLASS_HEADER__
#define MY_CLASS_HEADER__
#ifdef DLLCLASS_EXPORTS
#define IMPEXP __declspec(dllexport)
#else
#define IMPEXP __declspec(dllimport)
#endif /* DLLCLASS_EXPORTS */
class IMPEXP myClass
{
public:
myClass(void);
~myClass(void);
void set(int local);
int get(void);
private:
int number;
bool initialized;
};
extern "C" IMPEXP myClass * myClass_createInstance(void);
typedef myClass * (* myClass_createInstancePTR)(void);
#endif /* MY_CLASS_HEADER__ */
------------ myClass.cpp ------------
#include "myClass.h"
#include <iostream>
myClass::myClass(void)
{
std::cout << "Initialization" << std::endl;
initialized = false;
number = 0;
}
myClass::~myClass(void)
{
std::cout << "Destruction" << std::endl;
}
void myClass::set(int local)
{
initialized = true;
number = local;
}
int myClass::get(void)
{
if (!initialized)
{
throw -1;
}
return number;
}
myClass * myClass_createInstance(void)
{
return new myClass;
}
------------ DLLClass.cpp ------------
#include <windows.h>
BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved)
{
return TRUE;
}
Et voici les sources de l'application de test :
------------ DLLClassEXEDynamically.cpp ------------
#include "../DLLClass/myClass.h"
#include <stdlib.h>
#include <iostream>
#include <windows.h>
int main(int argc, char * argv[])
{
HMODULE hDLL;
myClass * check = NULL;
myClass_createInstancePTR myClass_createInstance = NULL;
hDLL = LoadLibrary("../DLLClass/Debug/DLLClass.dll");
if (NULL == hDLL)
{
std::cout << "Could not load the DLL" << std::endl;
return EXIT_FAILURE;
}
myClass_createInstance = (myClass_createInstancePTR)GetProcAddress(hDLL,
"myClass_createInstance");
std::cout << "Trying to create a new instance of the class" <<
std::endl;
check = myClass_createInstance();
try
{
std::cout << "The class contains: " << check->get() << std::endl;
}
catch(int)
{
std::cout << "An exception throwed" << std::endl;
}
check->set(5);
try
{
std::cout << "The class contains: " << check->get() << std::endl;
}
catch(int)
{
std::cout << "An exception throwed" << std::endl;
}
std::cout << "Trying to delete the instance of the class" << std::endl;
delete check;
FreeLibrary(hDLL);
return EXIT_SUCCESS;
}
La solution est d'utiliser des méthodes virtuelles. En effet, les fonctions
virtulles n'ont pas besoin d'être exportées, car on y accède par la
"v-table" de l'objet.
Utiliser des méthodes virtuelles permet aussi de séparer complètement
l'interface d'accès à la classe dans la DLL et son implémentation,
permettant facilement de changer le contenue de la DLL sans changer, ni même
recompiler l'exécutable tant que l'interface reste identique.
Note that only the factory fonction needs to be exported using
__declspec(dllexport). The class does not.
------- myClass.h -------
class myClass
{
public:
virtual ~myClass() {}
virtual void set(int value) = 0;
virtual int get() = 0;
};
extern "C" typedef myClass* (*myClass_createInstancePTR)();
------- myClassDLL.cpp ------
#include "myClass.h"
class myClassDll : public myClass
{
myClassDll();
virtual ~myClassDll();
virtual void set(int value);
virtual int get();
int number;
boolean initialized;
};
myClassDll::myClassDll()
{ ... }
myClassDll::~myClassDll()
{ ... }
void myClassDll::set(int value)
{ ... }
int myClassDll:get()
{ ... }
extern "C" __declspec(dllexport) myClass* myClass_createInstance()
{
return new myClassDll();
}
---- main.cpp ----
#include "myClass.h"
#include <windows.h>
int main()
{
hDLL = LoadLibrary("../DLLClass/Debug/DLLClass.dll");
myClass_createInstancePTR createInstance = (myClass_createInstancePTR)
GetProcAddress(hDLL, "myClass_createInstance");
myClass* instance = myClass_createInstance();
instance->set(5);
std::cout << "The class contains: " << instance->get() << std::endl;
delete instance;
FreeLibrary(hDLL);
return 0;
}
Frédéric Lachasse a écrit :"smu" wrote in message
news:4221aec1$0$4071$Bonjour,
Je cherche une méthode pour rendre une DLL de classe chargeable
dynamiquement.
J'ai trouvé pas mal d'information sur le net mais rien ne semble vouloir
fonctionner. Il me semble avoir compris que cela dépendait du
compilateur, la méthode semble varier entre VC++ 4 et VC++ 5. De même,
elle semble différente avec les compilateurs de chez Borland.
Moi, je travaille avec un VC++ 6.
Le problème se situe à l'édition des liens puisque les méthodes de la
classe ne peuvent, évidement, pas être résolu.
Quels sont les modifications à apporter pour que l'édition des liens se
passe bien ?
Je vous fournis les sources existants à ce jour.
D'avance merci.
smu
Voici les sources de la DLL :
------------ myClass.h ------------
#ifndef MY_CLASS_HEADER__
#define MY_CLASS_HEADER__
#ifdef DLLCLASS_EXPORTS
#define IMPEXP __declspec(dllexport)
#else
#define IMPEXP __declspec(dllimport)
#endif /* DLLCLASS_EXPORTS */
class IMPEXP myClass
{
public:
myClass(void);
~myClass(void);
void set(int local);
int get(void);
private:
int number;
bool initialized;
};
extern "C" IMPEXP myClass * myClass_createInstance(void);
typedef myClass * (* myClass_createInstancePTR)(void);
#endif /* MY_CLASS_HEADER__ */
------------ myClass.cpp ------------
#include "myClass.h"
#include <iostream>
myClass::myClass(void)
{
std::cout << "Initialization" << std::endl;
initialized = false;
number = 0;
}
myClass::~myClass(void)
{
std::cout << "Destruction" << std::endl;
}
void myClass::set(int local)
{
initialized = true;
number = local;
}
int myClass::get(void)
{
if (!initialized)
{
throw -1;
}
return number;
}
myClass * myClass_createInstance(void)
{
return new myClass;
}
------------ DLLClass.cpp ------------
#include <windows.h>
BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved)
{
return TRUE;
}
Et voici les sources de l'application de test :
------------ DLLClassEXEDynamically.cpp ------------
#include "../DLLClass/myClass.h"
#include <stdlib.h>
#include <iostream>
#include <windows.h>
int main(int argc, char * argv[])
{
HMODULE hDLL;
myClass * check = NULL;
myClass_createInstancePTR myClass_createInstance = NULL;
hDLL = LoadLibrary("../DLLClass/Debug/DLLClass.dll");
if (NULL == hDLL)
{
std::cout << "Could not load the DLL" << std::endl;
return EXIT_FAILURE;
}
myClass_createInstance =
(myClass_createInstancePTR)GetProcAddress(hDLL,
"myClass_createInstance");
std::cout << "Trying to create a new instance of the class" <<
std::endl;
check = myClass_createInstance();
try
{
std::cout << "The class contains: " << check->get() << std::endl;
}
catch(int)
{
std::cout << "An exception throwed" << std::endl;
}
check->set(5);
try
{
std::cout << "The class contains: " << check->get() << std::endl;
}
catch(int)
{
std::cout << "An exception throwed" << std::endl;
}
std::cout << "Trying to delete the instance of the class" << std::endl;
delete check;
FreeLibrary(hDLL);
return EXIT_SUCCESS;
}
La solution est d'utiliser des méthodes virtuelles. En effet, les
fonctions virtulles n'ont pas besoin d'être exportées, car on y accède
par la "v-table" de l'objet.
Utiliser des méthodes virtuelles permet aussi de séparer complètement
l'interface d'accès à la classe dans la DLL et son implémentation,
permettant facilement de changer le contenue de la DLL sans changer, ni
même recompiler l'exécutable tant que l'interface reste identique.
Note that only the factory fonction needs to be exported using
__declspec(dllexport). The class does not.
------- myClass.h -------
class myClass
{
public:
virtual ~myClass() {}
virtual void set(int value) = 0;
virtual int get() = 0;
};
extern "C" typedef myClass* (*myClass_createInstancePTR)();
------- myClassDLL.cpp ------
#include "myClass.h"
class myClassDll : public myClass
{
myClassDll();
virtual ~myClassDll();
virtual void set(int value);
virtual int get();
int number;
boolean initialized;
};
myClassDll::myClassDll()
{ ... }
myClassDll::~myClassDll()
{ ... }
void myClassDll::set(int value)
{ ... }
int myClassDll:get()
{ ... }
extern "C" __declspec(dllexport) myClass* myClass_createInstance()
{
return new myClassDll();
}
---- main.cpp ----
#include "myClass.h"
#include <windows.h>
int main()
{
hDLL = LoadLibrary("../DLLClass/Debug/DLLClass.dll");
myClass_createInstancePTR createInstance =
(myClass_createInstancePTR)
GetProcAddress(hDLL, "myClass_createInstance");
myClass* instance = myClass_createInstance();
instance->set(5);
std::cout << "The class contains: " << instance->get() << std::endl;
delete instance;
FreeLibrary(hDLL);
return 0;
}
Les modifications sont claires et fonctionnelles. Je peux charger la DLL à
la volée et créer des instances de ma classe. C'est parfait.
Merci beaucoup
Je vais peut-être abuser mais si je veux utiliser cette DLL en statique au
travers du fichier ".lib", j'obtiens une erreur à l'édition des liens :
DLLMainEXEStatically.obj : error LNK2001: unresolved external symbol
"public: __thiscall myClassDLL::myClassDLL(void)" (??0myClassDLL@@)
Il y a t-il une solution à ce problème ?
Frédéric Lachasse a écrit :
"smu" <pas@d.adresse> wrote in message
news:4221aec1$0$4071$636a15ce@news.free.fr...
Bonjour,
Je cherche une méthode pour rendre une DLL de classe chargeable
dynamiquement.
J'ai trouvé pas mal d'information sur le net mais rien ne semble vouloir
fonctionner. Il me semble avoir compris que cela dépendait du
compilateur, la méthode semble varier entre VC++ 4 et VC++ 5. De même,
elle semble différente avec les compilateurs de chez Borland.
Moi, je travaille avec un VC++ 6.
Le problème se situe à l'édition des liens puisque les méthodes de la
classe ne peuvent, évidement, pas être résolu.
Quels sont les modifications à apporter pour que l'édition des liens se
passe bien ?
Je vous fournis les sources existants à ce jour.
D'avance merci.
smu
Voici les sources de la DLL :
------------ myClass.h ------------
#ifndef MY_CLASS_HEADER__
#define MY_CLASS_HEADER__
#ifdef DLLCLASS_EXPORTS
#define IMPEXP __declspec(dllexport)
#else
#define IMPEXP __declspec(dllimport)
#endif /* DLLCLASS_EXPORTS */
class IMPEXP myClass
{
public:
myClass(void);
~myClass(void);
void set(int local);
int get(void);
private:
int number;
bool initialized;
};
extern "C" IMPEXP myClass * myClass_createInstance(void);
typedef myClass * (* myClass_createInstancePTR)(void);
#endif /* MY_CLASS_HEADER__ */
------------ myClass.cpp ------------
#include "myClass.h"
#include <iostream>
myClass::myClass(void)
{
std::cout << "Initialization" << std::endl;
initialized = false;
number = 0;
}
myClass::~myClass(void)
{
std::cout << "Destruction" << std::endl;
}
void myClass::set(int local)
{
initialized = true;
number = local;
}
int myClass::get(void)
{
if (!initialized)
{
throw -1;
}
return number;
}
myClass * myClass_createInstance(void)
{
return new myClass;
}
------------ DLLClass.cpp ------------
#include <windows.h>
BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved)
{
return TRUE;
}
Et voici les sources de l'application de test :
------------ DLLClassEXEDynamically.cpp ------------
#include "../DLLClass/myClass.h"
#include <stdlib.h>
#include <iostream>
#include <windows.h>
int main(int argc, char * argv[])
{
HMODULE hDLL;
myClass * check = NULL;
myClass_createInstancePTR myClass_createInstance = NULL;
hDLL = LoadLibrary("../DLLClass/Debug/DLLClass.dll");
if (NULL == hDLL)
{
std::cout << "Could not load the DLL" << std::endl;
return EXIT_FAILURE;
}
myClass_createInstance =
(myClass_createInstancePTR)GetProcAddress(hDLL,
"myClass_createInstance");
std::cout << "Trying to create a new instance of the class" <<
std::endl;
check = myClass_createInstance();
try
{
std::cout << "The class contains: " << check->get() << std::endl;
}
catch(int)
{
std::cout << "An exception throwed" << std::endl;
}
check->set(5);
try
{
std::cout << "The class contains: " << check->get() << std::endl;
}
catch(int)
{
std::cout << "An exception throwed" << std::endl;
}
std::cout << "Trying to delete the instance of the class" << std::endl;
delete check;
FreeLibrary(hDLL);
return EXIT_SUCCESS;
}
La solution est d'utiliser des méthodes virtuelles. En effet, les
fonctions virtulles n'ont pas besoin d'être exportées, car on y accède
par la "v-table" de l'objet.
Utiliser des méthodes virtuelles permet aussi de séparer complètement
l'interface d'accès à la classe dans la DLL et son implémentation,
permettant facilement de changer le contenue de la DLL sans changer, ni
même recompiler l'exécutable tant que l'interface reste identique.
Note that only the factory fonction needs to be exported using
__declspec(dllexport). The class does not.
------- myClass.h -------
class myClass
{
public:
virtual ~myClass() {}
virtual void set(int value) = 0;
virtual int get() = 0;
};
extern "C" typedef myClass* (*myClass_createInstancePTR)();
------- myClassDLL.cpp ------
#include "myClass.h"
class myClassDll : public myClass
{
myClassDll();
virtual ~myClassDll();
virtual void set(int value);
virtual int get();
int number;
boolean initialized;
};
myClassDll::myClassDll()
{ ... }
myClassDll::~myClassDll()
{ ... }
void myClassDll::set(int value)
{ ... }
int myClassDll:get()
{ ... }
extern "C" __declspec(dllexport) myClass* myClass_createInstance()
{
return new myClassDll();
}
---- main.cpp ----
#include "myClass.h"
#include <windows.h>
int main()
{
hDLL = LoadLibrary("../DLLClass/Debug/DLLClass.dll");
myClass_createInstancePTR createInstance =
(myClass_createInstancePTR)
GetProcAddress(hDLL, "myClass_createInstance");
myClass* instance = myClass_createInstance();
instance->set(5);
std::cout << "The class contains: " << instance->get() << std::endl;
delete instance;
FreeLibrary(hDLL);
return 0;
}
Les modifications sont claires et fonctionnelles. Je peux charger la DLL à
la volée et créer des instances de ma classe. C'est parfait.
Merci beaucoup
Je vais peut-être abuser mais si je veux utiliser cette DLL en statique au
travers du fichier ".lib", j'obtiens une erreur à l'édition des liens :
DLLMainEXEStatically.obj : error LNK2001: unresolved external symbol
"public: __thiscall myClassDLL::myClassDLL(void)" (??0myClassDLL@@QAE@XZ)
Il y a t-il une solution à ce problème ?
Frédéric Lachasse a écrit :"smu" wrote in message
news:4221aec1$0$4071$Bonjour,
Je cherche une méthode pour rendre une DLL de classe chargeable
dynamiquement.
J'ai trouvé pas mal d'information sur le net mais rien ne semble vouloir
fonctionner. Il me semble avoir compris que cela dépendait du
compilateur, la méthode semble varier entre VC++ 4 et VC++ 5. De même,
elle semble différente avec les compilateurs de chez Borland.
Moi, je travaille avec un VC++ 6.
Le problème se situe à l'édition des liens puisque les méthodes de la
classe ne peuvent, évidement, pas être résolu.
Quels sont les modifications à apporter pour que l'édition des liens se
passe bien ?
Je vous fournis les sources existants à ce jour.
D'avance merci.
smu
Voici les sources de la DLL :
------------ myClass.h ------------
#ifndef MY_CLASS_HEADER__
#define MY_CLASS_HEADER__
#ifdef DLLCLASS_EXPORTS
#define IMPEXP __declspec(dllexport)
#else
#define IMPEXP __declspec(dllimport)
#endif /* DLLCLASS_EXPORTS */
class IMPEXP myClass
{
public:
myClass(void);
~myClass(void);
void set(int local);
int get(void);
private:
int number;
bool initialized;
};
extern "C" IMPEXP myClass * myClass_createInstance(void);
typedef myClass * (* myClass_createInstancePTR)(void);
#endif /* MY_CLASS_HEADER__ */
------------ myClass.cpp ------------
#include "myClass.h"
#include <iostream>
myClass::myClass(void)
{
std::cout << "Initialization" << std::endl;
initialized = false;
number = 0;
}
myClass::~myClass(void)
{
std::cout << "Destruction" << std::endl;
}
void myClass::set(int local)
{
initialized = true;
number = local;
}
int myClass::get(void)
{
if (!initialized)
{
throw -1;
}
return number;
}
myClass * myClass_createInstance(void)
{
return new myClass;
}
------------ DLLClass.cpp ------------
#include <windows.h>
BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved)
{
return TRUE;
}
Et voici les sources de l'application de test :
------------ DLLClassEXEDynamically.cpp ------------
#include "../DLLClass/myClass.h"
#include <stdlib.h>
#include <iostream>
#include <windows.h>
int main(int argc, char * argv[])
{
HMODULE hDLL;
myClass * check = NULL;
myClass_createInstancePTR myClass_createInstance = NULL;
hDLL = LoadLibrary("../DLLClass/Debug/DLLClass.dll");
if (NULL == hDLL)
{
std::cout << "Could not load the DLL" << std::endl;
return EXIT_FAILURE;
}
myClass_createInstance =
(myClass_createInstancePTR)GetProcAddress(hDLL,
"myClass_createInstance");
std::cout << "Trying to create a new instance of the class" <<
std::endl;
check = myClass_createInstance();
try
{
std::cout << "The class contains: " << check->get() << std::endl;
}
catch(int)
{
std::cout << "An exception throwed" << std::endl;
}
check->set(5);
try
{
std::cout << "The class contains: " << check->get() << std::endl;
}
catch(int)
{
std::cout << "An exception throwed" << std::endl;
}
std::cout << "Trying to delete the instance of the class" << std::endl;
delete check;
FreeLibrary(hDLL);
return EXIT_SUCCESS;
}
La solution est d'utiliser des méthodes virtuelles. En effet, les
fonctions virtulles n'ont pas besoin d'être exportées, car on y accède
par la "v-table" de l'objet.
Utiliser des méthodes virtuelles permet aussi de séparer complètement
l'interface d'accès à la classe dans la DLL et son implémentation,
permettant facilement de changer le contenue de la DLL sans changer, ni
même recompiler l'exécutable tant que l'interface reste identique.
Note that only the factory fonction needs to be exported using
__declspec(dllexport). The class does not.
------- myClass.h -------
class myClass
{
public:
virtual ~myClass() {}
virtual void set(int value) = 0;
virtual int get() = 0;
};
extern "C" typedef myClass* (*myClass_createInstancePTR)();
------- myClassDLL.cpp ------
#include "myClass.h"
class myClassDll : public myClass
{
myClassDll();
virtual ~myClassDll();
virtual void set(int value);
virtual int get();
int number;
boolean initialized;
};
myClassDll::myClassDll()
{ ... }
myClassDll::~myClassDll()
{ ... }
void myClassDll::set(int value)
{ ... }
int myClassDll:get()
{ ... }
extern "C" __declspec(dllexport) myClass* myClass_createInstance()
{
return new myClassDll();
}
---- main.cpp ----
#include "myClass.h"
#include <windows.h>
int main()
{
hDLL = LoadLibrary("../DLLClass/Debug/DLLClass.dll");
myClass_createInstancePTR createInstance =
(myClass_createInstancePTR)
GetProcAddress(hDLL, "myClass_createInstance");
myClass* instance = myClass_createInstance();
instance->set(5);
std::cout << "The class contains: " << instance->get() << std::endl;
delete instance;
FreeLibrary(hDLL);
return 0;
}
Les modifications sont claires et fonctionnelles. Je peux charger la DLL à
la volée et créer des instances de ma classe. C'est parfait.
Merci beaucoup
Je vais peut-être abuser mais si je veux utiliser cette DLL en statique au
travers du fichier ".lib", j'obtiens une erreur à l'édition des liens :
DLLMainEXEStatically.obj : error LNK2001: unresolved external symbol
"public: __thiscall myClassDLL::myClassDLL(void)" (??0myClassDLL@@)
Il y a t-il une solution à ce problème ?