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
restituisceNULL
o un handle di risorse non corretto.DllGetClassObject
,DllCanUnloadNow
e leUpdateRegistry
funzioni membro ,RevokeAll
Revoke
, eRegisterAll
diCOleObjectFactory
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.dll
dell'estensione MFC di debug MFC , MFCDxxD.dll
e 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 relativaCWinApp::InitInstance
funzione. Assicurarsi che questa chiamata venga eseguita prima di qualsiasi chiamata di classe base o qualsiasi codice aggiunto che accede aMFCDxxD.dll
. Questa funzione non accetta parametri e restituiscevoid
.Per il supporto OLE, aggiungere una chiamata alla
AfxOleInitModule
DLL MFC regolare, la relativaCWinApp::InitInstance
funzione. LaCOleControlModule::InitInstance
funzione chiamaAfxOleInitModule
già, quindi se si compila un controllo OLE e si usaCOleControlModule
, non è consigliabile aggiungere questa chiamata aAfxOleInitModule
.Per il supporto di Sockets, aggiungere una chiamata alla
AfxNetInitModule
NORMALE DLL MFC inCWinApp::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 CWinApp
derivato 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;
}