Uso di DLL MFC di estensione per database, OLE e Sockets nelle DLL MFC regolari

Quando si usa una DLL di estensione MFC da una NORMALE DLL MFC, se la DLL dell'estensione MFC non è cablata nella CDynLinkLibrary catena di oggetti della NORMALE DLL MFC, è possibile che si verifichino uno o più problemi correlati. Poiché le versioni di debug del database MFC, OLE e Sockets supportano DLL vengono implementate come DLL di estensione MFC, potrebbero verificarsi problemi simili se si usano queste funzionalità MFC, anche se non si usa esplicitamente alcuna DLL di estensione MFC. Alcuni sintomi sono:

  • Quando si tenta di deserializzare un oggetto di un tipo di classe definito nella DLL dell'estensione MFC, il messaggio "Avviso: Impossibile caricare CYourClass dall'archivio. La classe non è definita." viene visualizzata nella finestra di debug TRACE e l'oggetto non riesce a serializzare.

  • Eccezione che indica che potrebbe essere generata una classe non valida.

  • Le risorse archiviate nella DLL dell'estensione MFC non vengono caricate perché AfxFindResourceHandle restituisce NULL o un handle di risorse non corretto.

  • DllGetClassObject, DllCanUnloadNowe le UpdateRegistryfunzioni membro , RevokeAllRevoke, e RegisterAll di COleObjectFactory non riescono a individuare una class factory definita nella DLL dell'estensione MFC.

  • AfxDoForAllClasses non funziona per alcuna classe nella DLL dell'estensione MFC.

  • Non è possibile caricare database, socket o risorse OLE standard. Ad esempio, restituisce AfxLoadString(AFX_IDP_SQL_CONNECT_FAIL) una stringa vuota, anche quando la normale DLL MFC usa correttamente le classi di database MFC.

La soluzione a questi problemi consiste nel creare ed esportare una funzione di inizializzazione nella DLL dell'estensione MFC che crea un CDynLinkLibrary oggetto . Chiamare questa funzione di inizializzazione esattamente una volta da ogni normale DLL MFC che usa la DLL dell'estensione MFC.

Supporto di socket MFC OLE, MFC (o DAO) o MFC

Se si usa un database MFC, un database MFC (o DAO) o un supporto MFC Sockets nella DLL MFC normale, rispettivamente, le DLL MFCOxxD.dlldell'estensione MFC di debug MFC , MFCDxxD.dlle MFCNxxD.dll (dove xx è il numero di versione) vengono collegate automaticamente. Chiamare una funzione di inizializzazione predefinita per ognuna delle DLL in uso:

  • Per il supporto del database, aggiungere una chiamata alla AfxDbInitModule NORMALE DLL MFC nella relativa CWinApp::InitInstance funzione. Assicurarsi che questa chiamata venga eseguita prima di qualsiasi chiamata di classe base o qualsiasi codice aggiunto che accede a MFCDxxD.dll. Questa funzione non accetta parametri e restituisce void.

  • Per il supporto OLE, aggiungere una chiamata alla AfxOleInitModule DLL MFC regolare, la relativa CWinApp::InitInstance funzione. La COleControlModule::InitInstance funzione chiama AfxOleInitModule già, quindi se si compila un controllo OLE e si usa COleControlModule, non è consigliabile aggiungere questa chiamata a AfxOleInitModule.

  • Per il supporto di Sockets, aggiungere una chiamata alla AfxNetInitModule NORMALE DLL MFC in CWinApp::InitInstance.

Le build di rilascio di DLL E applicazioni MFC non usano DLL separate per il supporto di database, socket o OLE. Tuttavia, è possibile chiamare queste funzioni di inizializzazione in modalità di rilascio.

Oggetti CDynLinkLibrary

Durante ogni operazione indicata all'inizio di questo articolo, MFC deve cercare un valore o un oggetto specifico. Ad esempio, durante la deserializzazione, MFC deve eseguire ricerche in tutte le classi di runtime attualmente disponibili per trovare le corrispondenze tra gli oggetti nell'archivio con la classe di runtime appropriata.

Come parte di queste ricerche, MFC analizza tutte le DLL dell'estensione MFC in uso camminando su una catena di CDynLinkLibrary oggetti. CDynLinkLibrary gli oggetti si collegano automaticamente a una catena durante la costruzione e vengono creati da ogni DLL di estensione MFC a sua volta durante l'inizializzazione. Ogni modulo (applicazione o DLL MFC normale) ha una propria catena di CDynLinkLibrary oggetti.

Affinché una DLL di estensione MFC venga cablata in una CDynLinkLibrary catena, deve creare un CDynLinkLibrary oggetto nel contesto di ogni modulo che usa la DLL dell'estensione MFC. Per usare una DLL di estensione MFC nelle normali DLL MFC, la DLL dell'estensione deve fornire una funzione di inizializzazione esportata che crea un CDynLinkLibrary oggetto . Ogni NORMALE DLL MFC che usa la DLL dell'estensione MFC deve chiamare la funzione di inizializzazione esportata.

Se si userà solo una DLL di estensione MFC da un'applicazione MFC e mai da una normale DLL MFC, è sufficiente creare l'oggetto CDynLinkLibrary nella funzione DLL DllMain dell'estensione MFC. Si tratta del codice DLL MFC Della procedura guidata MFC. Quando si carica una DLL di estensione MFC in modo implicito, DllMain carica ed esegue prima dell'avvio dell'applicazione. Tutte CDynLinkLibrary le creazioni sono cablate in una catena predefinita che la DLL MFC riserva per un'applicazione MFC.

È consigliabile avere più CDynLinkLibrary oggetti da una DLL di estensione MFC in una catena. È particolarmente vero se la DLL dell'estensione MFC può essere scaricata dinamicamente dalla memoria. Non chiamare la funzione di inizializzazione più di una volta da un modulo.

Codice di esempio

Questo codice di esempio presuppone che la NORMALE DLL MFC si collega in modo implicito alla DLL dell'estensione MFC. Per collegarsi in modo implicito, collegarsi alla libreria di importazione (file LIB) della DLL dell'estensione MFC quando si compila la NORMALE DLL MFC.

Le righe seguenti devono trovarsi nell'origine della DLL dell'estensione 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
}

Assicurarsi di esportare la funzione InitYourExtDLL . È possibile usare __declspec(dllexport)o esportarlo nel file DEF per la DLL, come illustrato di seguito:

// YourExtDLL.Def:
LIBRARY      YOUREXTDLL
CODE         PRELOAD MOVEABLE DISCARDABLE
DATA         PRELOAD SINGLE
EXPORTS
    InitYourExtDLL

Aggiungere una chiamata al InitInstance membro dell'oggetto CWinAppderivato da -in ogni normale DLL MFC usando la DLL dell'estensione 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;
}

Cosa vuoi fare?

Scegliere l'argomento su cui visualizzare maggiori informazioni

Vedi anche

MFC (DLL di estensione)