Utilisation de DLL d’extension de MFC de type base de données, OLE et sockets dans des DLL MFC normales
Lorsque vous utilisez une DLL d’extension MFC à partir d’une DLL MFC standard, si la DLL d’extension MFC n’est pas câblée dans la chaîne d’objets de la CDynLinkLibrary
DLL MFC standard, vous risquez d’rencontrer un ou plusieurs problèmes connexes. Étant donné que les versions de débogage de la base de données MFC, OLE et Sockets prennent en charge les DLL d’extension MFC sont implémentées en tant que DLL d’extension MFC, vous pouvez rencontrer des problèmes similaires si vous utilisez ces fonctionnalités MFC, même si vous n’utilisez pas explicitement l’une de vos propres DLL d’extension MFC. Voici quelques symptômes :
Lorsque vous tentez de désérialiser un objet d’un type de classe défini dans la DLL d’extension MFC, le message « Avertissement : Impossible de charger CYourClass à partir de l’archive. Classe non définie. » apparaît dans la fenêtre de débogage TRACE et l’objet ne parvient pas à sérialiser.
Une exception indiquant que la classe incorrecte peut être levée.
Les ressources stockées dans la DLL d’extension MFC ne parviennent pas à se charger, car
AfxFindResourceHandle
elles sont retournéesNULL
ou un handle de ressource incorrect.DllGetClassObject
,DllCanUnloadNow
et lesUpdateRegistry
fonctions membres et lesRegisterAll
Revoke
RevokeAll
fonctions membres de l’échec deCOleObjectFactory
localisation d’une fabrique de classe définie dans la DLL d’extension MFC.AfxDoForAllClasses
ne fonctionne pas pour les classes de la DLL d’extension MFC.La base de données, les sockets ou les ressources OLE standard ne peuvent pas être chargées. Par exemple,
AfxLoadString(AFX_IDP_SQL_CONNECT_FAIL)
retourne une chaîne vide, même lorsque la DLL MFC standard utilise correctement les classes de base de données MFC.
La solution à ces problèmes consiste à créer et exporter une fonction d’initialisation dans la DLL d’extension MFC qui crée un CDynLinkLibrary
objet. Appelez cette fonction d’initialisation exactement une fois à partir de chaque DLL MFC standard qui utilise la DLL d’extension MFC.
Prise en charge des sockets MFC OLE, MFC Database (ou DAO) ou MFC
Si vous utilisez une dll MFC OLE, MFC Database (ou DAO) ou MFC Sockets pris en charge dans votre DLL MFC standard, respectivement, les DLL MFCOxxD.dll
d’extension MFC de débogage MFC , MFCDxxD.dll
et MFCNxxD.dll
(où xx est le numéro de version) sont liés automatiquement. Appelez une fonction d’initialisation prédéfinie pour chacune des DLL que vous utilisez :
Pour la prise en charge de la base de données, ajoutez un appel à
AfxDbInitModule
votre DLL MFC standard dans saCWinApp::InitInstance
fonction. Assurez-vous que cet appel se produit avant tout appel de classe de base ou tout code ajouté qui accède auMFCDxxD.dll
. Cette fonction ne prend aucun paramètre et retournevoid
.Pour la prise en charge OLE, ajoutez un appel à
AfxOleInitModule
votre DLL MFC normale.CWinApp::InitInstance
La fonction appelleAfxOleInitModule
déjà. ParCOleControlModule::InitInstance
conséquent, si vous créez un contrôle OLE et que vous utilisezCOleControlModule
, vous ne devez pas ajouter cet appel àAfxOleInitModule
.Pour la prise en charge des sockets, ajoutez un appel à
AfxNetInitModule
votre DLL MFC standard dansCWinApp::InitInstance
.
Les builds de versions de DLL MFC et d’applications n’utilisent pas de DLL distinctes pour la base de données, les sockets ou la prise en charge OLE. Toutefois, il est sûr d’appeler ces fonctions d’initialisation en mode mise en production.
Objets CDynLinkLibrary
Pendant chaque opération mentionnée au début de cet article, MFC doit rechercher une valeur ou un objet particulier. Par exemple, lors de la désérialisation, MFC doit effectuer une recherche dans toutes les classes d’exécution actuellement disponibles pour faire correspondre des objets dans l’archive avec leur classe d’exécution appropriée.
Dans le cadre de ces recherches, MFC analyse toutes les DLL d’extension MFC utilisées en marchant une chaîne d’objets CDynLinkLibrary
. CDynLinkLibrary
les objets attachent automatiquement à une chaîne pendant leur construction et sont créés par chaque DLL d’extension MFC à leur tour lors de l’initialisation. Chaque module (DLL MFC ou application standard) possède sa propre chaîne d’objets CDynLinkLibrary
.
Pour qu’une DLL d’extension MFC soit câblée dans une CDynLinkLibrary
chaîne, elle doit créer un CDynLinkLibrary
objet dans le contexte de chaque module qui utilise la DLL d’extension MFC. Pour utiliser une DLL d’extension MFC dans des DLL MFC standard, la DLL d’extension doit fournir une fonction d’initialisation exportée qui crée un CDynLinkLibrary
objet. Chaque DLL MFC standard qui utilise la DLL d’extension MFC doit appeler la fonction d’initialisation exportée.
Si vous n’utiliserez qu’une DLL d’extension MFC à partir d’une application MFC et jamais d’une DLL MFC normale, il suffit de créer l’objet CDynLinkLibrary
dans la fonction DLL DllMain
d’extension MFC. C’est ce que fait le code DLL de l’Assistant DLL MFC de l’Assistant DLL MFC. Lors du chargement implicite d’une DLL d’extension MFC, DllMain
charge et s’exécute avant le démarrage de l’application. Toutes les CDynLinkLibrary
créations sont câblées dans une chaîne par défaut que la DLL MFC réserve pour une application MFC.
Il est difficile d’avoir plusieurs CDynLinkLibrary
objets d’une DLL d’extension MFC dans n’importe quelle chaîne. Il est particulièrement vrai si la DLL d’extension MFC peut être déchargée dynamiquement à partir de la mémoire. N’appelez pas la fonction d’initialisation plusieurs fois à partir d’un module.
Exemple de code
Cet exemple de code suppose que la DLL MFC régulière est implicitement liée à la DLL d’extension MFC. Pour lier implicitement, liez la bibliothèque d’importation (fichier LIB) de la DLL d’extension MFC lorsque vous générez la DLL MFC standard.
Les lignes suivantes doivent se trouver dans la source de la DLL d’extension MFC :
// YourExtDLL.cpp:
// standard MFC extension DLL routines
#include "afxdllx.h"
static AFX_EXTENSION_MODULE extensionDLL;
extern "C" int APIENTRY
DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
{
if (dwReason == DLL_PROCESS_ATTACH)
{
// MFC extension DLL one-time initialization
if (!AfxInitExtensionModule(extensionDLL, hInstance))
return 0;
}
return 1; // ok
}
// Exported DLL initialization is run in context of
// application or regular MFC DLL
extern "C" void WINAPI InitYourExtDLL()
{
// create a new CDynLinkLibrary for this app
new CDynLinkLibrary(extensionDLL);
// add other initialization here
}
Veillez à exporter la fonction InitYourExtDLL . Vous pouvez l’utiliser __declspec(dllexport)
ou l’exporter dans le fichier DEF de votre DLL, comme illustré ici :
// YourExtDLL.Def:
LIBRARY YOUREXTDLL
CODE PRELOAD MOVEABLE DISCARDABLE
DATA PRELOAD SINGLE
EXPORTS
InitYourExtDLL
Ajoutez un appel au membre de l’objet CWinApp
dérivé dans chaque DLL MFC normale à InitInstance
l’aide de la DLL d’extension MFC :
// YourRegularDLL.cpp:
class CYourRegularDLL : public CWinApp
{
public:
virtual BOOL InitInstance(); // Initialization
virtual int ExitInstance(); // Termination
// nothing special for the constructor
CYourRegularDLL(LPCTSTR pszAppName) : CWinApp(pszAppName) { }
};
BOOL CYourRegularDLL::InitInstance()
{
// any DLL initialization goes here
TRACE0("YOUR regular MFC DLL initializing\n");
// wire any MFC extension DLLs into CDynLinkLibrary chain
InitYourExtDLL();
return TRUE;
}