Používání databáze, technologie OLE a rozšíření soketů DLL v běžných knihovnách DLL
Při použití rozšiřující knihovny DLL z obvyklé knihovny DLL, pokud rozšiřující knihovna DLL není připojená do objektu řetězce CDynLinkLibrary obvyklé DLL knihovny, můžete narazit na jednu nebo více sad souvisejících problémů.Můžete vidět podobné problémy, protože ladící verze databází knihovny MFC, technologie OLE a soketů podporují DLL knihovny, které jsou implementovány jako rozšiřující DLL knihovny, pokud používáte tyto funkce knihovny MFC, i pokud explicitně nepoužíváte některé z Vašich rozšiřujících DLL knihoven.Některé příznaky jsou:
Při pokusu o deserializaci objektu typu třídy definované v rozšiřující DLL Knihovně, zprávu "Upozornění: Nelze načíst CYourClass z archívu.V okně ladění TRACE se zobrazí zpráva, že třída není definována, a serializace objektu se nezdaří.
Může být vyvolána výjimka označující chybnou třídu.
Načtení uložených prostředků v rozšiřující DLL knihovně selže, protože AfxFindResourceHandle vrátí hodnotu NULL nebo nesprávnou obslužnou rutinu prostředku.
DllGetClassObject, DllCanUnloadNow a členské funkce UpdateRegistry, Revoke, RevokeAll, a RegisterAll objektu COleObjectFactory nenaleznou objekt pro vytváření tříd, definovaný v rozšiřující DLL knihovně.
AfxDoForAllClasses nefunguje pro všechny třídy v rozšiřující DLL knihovně.
Nepodaří se načíst standartní databázovou knihovnu MFC, sokety nebo prostředky technologie OLE.Například AfxLoadString(AFX_IDP_SQL_CONNECT_FAIL) vrátí prázdný řetězec, i když obvyklá DLL knihovna správně používá databázové třídy knihovny MFC.
Řešením těchto problémů je vytvoření a exportování inicializační funkce v rozšiřující knihovně DLL, která vytvoří objekt CDynLinkLibrary.Zavolejte tuto inicializační funkci přesně jednou z každé obvyklé DLL knihovny, která používá rozšiřující DLL knihovnu.
Technologie OLE knihovny MFC, databáze knihovny MFC (nebo rozhraní DAO) nebo podpora soketů knihovny MFC
Pokud používáte jakékoliv technologie OLE knihovny MFC, databázi knihovny MFC (nebo rozhraní DAO), nebo podporuje-li knihovna MFC sokety, respektive ladí-li knihovna MFC s příponou knihoven DLL MFCOxxD.dll, MFCDxxD.dll, a MFCNxxD.dll (kde xx je číslo verze) jsou automatiky propojeny.Musíte zavolat předdefinovanou inicializační funkci pro každou vámi používanou DLL knihovnu.
Pro podporu databáze přidejte volání AfxDbInitModule do funkce CWinApp::InitInstance vaší obvyklé DLL knihovny. Přesvědčte se, zda k tomuto volání dochází před jakýmkoliv voláním základní třídy nebo jakýmkoliv přidaným kódem, který přistupuje ke knihovně MFCDxxD.dllTato funkce nebere žádné parametry a vrací hodnotu typu void.
Pro podporu technologie OLE přidejte volání AfxOleInitModule do funkce CWinApp::InitInstance vaší obvyklé DLL knihovny. Všimněte si, že funkce COleControlModule InitInstance již volá AfxOleInitModule, takže pokud vytváříte ovládací prvek technologie OLE a používáte COleControlModule, neměli by jste přidávat toto volání do AfxOleInitModule.
Pro podporu technologie OLE přidejte volání AfxNetInitModule do funkce CWinApp::InitInstance vaší obvyklé DLL knihovny.
Mějte na paměti, že vydaná sestavení knihoven MFC DLL a aplikací nepoužívají podporu samostatných DLL knihoven pro databázi, sokety technologii OLE.Avšak je bezpečné volat tyto inicializační funkce v režimu vydání.
Objekty CDynLinkLibrary
V průběhu každé uvedené operace a na začátku tohoto tématu, potřebovala knihovna MFC vyhledat požadovanou hodnotu nebo objekt.Například během deserializace potřebuje knihovna MFC prohledávat všechny aktuálně dostupné třídy modulu runtime pro porovnání objektů v archivu s jejich správnou třídou modulu runtime.
Jako součást těchto hledání prohledává knihovna MFC skrz všechny rozšiřující DLL knihovny použité při prohledávání řetězce objektů CDynLinkLibrary.Objekty CDynLinkLibrary se automaticky připojí k řetězci během jejich konstrukce a jsou vytvářeny každou rozšiřující DLL knihovnou opět při inicializaci.Kromě toho má každý modul (aplikace nebo obvyklá knihovna DLL) vlastní řetězec objektů CDynLinkLibrary.
Připojení rozšiřující knihovny DLL do řetězce CDynLinkLibrary, musí vytvořit objekt CDynLinkLibrary v rámci každého modulu, který používá rozšiřující DLL knihovnu.Proto pokud je rozšiřující DLL knihovna použita z obvyklých DLL knihoven, musí poskytnou exportovanou inicializační funkci, která vytvoří objekt CDynLinkLibrary.Každá obvyklá DLL knihovna, která používá rozšiřující DLL knihovnu, musí volat exportovanou inicializační funkci.
Pokud je rozšiřující DLL knihovna použita pouze z aplikace knihovny MFC (.exe) a nikdy z obvyklé DLL knihovny, pak stačí vytvořit objekt CDynLinkLibrary v rozšiřující DLL knihovně DllMain.To je to, co provede kód rozšiřující DLL knihovny průvodce knihovny MFC DLL.Při implicitním načítání rozšiřující DLL knihovny, načte a spustí DllMain před spuštěním aplikace. Jakákoliv vytvoření CDynLinkLibrary jsou zapojeny do výchozího řetězce, takže je knihovna MFC DLL vyhrazena pro aplikaci knihovny MFC.
Uvědomte si, že je špatný nápad, mít více objektů CDynLinkLibrary z jedné rozšiřující DLL knihovny v jakémkoliv řetězci, zejména pokud bude rozšiřující DLL knihovna dynamicky uvolněna z paměti.Nevolejte inicializační funkci více než jednou z jakéhokoliv modulu.
Ukázka kódu
Tento ukázkový kód předpokládá, že je obvyklá DLL knihovna implicitně propojená do rozšiřující DLL knihovny.To je provedeno při propojení do vložené knihovny (.lib) rozšiřující DLL knihovny při sestavení obvyklé DLL knihovny.
Následující řádky mohou být ve zdroji rozšiřující DLL knihovny:
// YourExtDLL.cpp:
// standard MFC extension DLL routines
#include "afxdllx.h"
static AFX_EXTENSION_MODULE NEAR extensionDLL = { NULL, NULL };
extern "C" int APIENTRY
DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
{
if (dwReason == DLL_PROCESS_ATTACH)
{
// 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 DLL
extern "C" void WINAPI InitYourExtDLL()
{
// create a new CDynLinkLibrary for this app
new CDynLinkLibrary(extensionDLL);
// add other initialization here
}
Přesvědčte se, zda jste exportovali funkce InitYourExtDLL.To může být provedeno pomocí __declspec(dllexport) nebo ve vašem .def souboru DLL knihovny následujícím způsobem:
// YourExtDLL.Def:
LIBRARY YOUREXTDLL
CODE PRELOAD MOVEABLE DISCARDABLE
DATA PRELOAD SINGLE
EXPORTS
InitYourExtDLL
Přidejte volání člena InitInstance odvozeného objektu CWinApp v každé obvyklé DLL knihovně, používající rozšiřující DLL knihovnu:
// 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 DLL initializing\n");
// wire any extension DLLs into CDynLinkLibrary chain
InitYourExtDLL();
return TRUE;
}