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ées NULL ou un handle de ressource incorrect.

  • DllGetClassObject, DllCanUnloadNowet les UpdateRegistryfonctions membres et les RegisterAllRevokeRevokeAllfonctions membres de l’échec de COleObjectFactory 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.dlld’extension MFC de débogage MFC , MFCDxxD.dllet 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 sa CWinApp::InitInstance fonction. Assurez-vous que cet appel se produit avant tout appel de classe de base ou tout code ajouté qui accède au MFCDxxD.dll. Cette fonction ne prend aucun paramètre et retourne void.

  • Pour la prise en charge OLE, ajoutez un appel à AfxOleInitModule votre DLL MFC normale.CWinApp::InitInstance La fonction appelle AfxOleInitModule déjà. Par COleControlModule::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 dans CWinApp::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 CWinAppdé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;
}

Que voulez-vous faire ?

Sur quels éléments souhaitez-vous obtenir des informations supplémentaires ?

Voir aussi

DLL d’extension de MFC