Sdílet prostřednictvím


Používání databázových, OLE a soketových rozšiřujících knihoven MFC DLL v běžných knihovnách MFC DLL

Pokud používáte knihovnu DLL rozšíření MFC z běžné knihovny MFC DLL, není-li knihovna DLL rozšíření MFC připojena k CDynLinkLibrary řetězci objektů běžné knihovny MFC DLL, můžete narazit na jeden nebo více souvisejících problémů. Vzhledem k tomu, že ladicí verze knihovny DLL databáze MFC, OLE a soketů podporují knihovny DLL, můžou se při používání těchto funkcí MFC zobrazit podobné problémy, i když explicitně nepoužíváte žádné vlastní knihovny DLL rozšíření MFC. Mezi příznaky patří mimo jiné:

  • Při pokusu o deserializaci objektu typu třídy definované v knihovně DLL rozšíření MFC, zpráva "Upozornění: Nelze načíst CYourClass z archivu. Třída není definována." zobrazí se v okně ladění TRACE a objekt se nepodaří serializovat.

  • Může dojít k výjimce označující chybnou třídu.

  • Prostředky uložené v knihovně DLL rozšíření MFC se nepodaří načíst, protože AfxFindResourceHandle vrací NULL nebo nesprávné popisovač prostředků.

  • DllGetClassObject, DllCanUnloadNowa , RevokeRevokeAlla UpdateRegistry, a RegisterAll členské funkce COleObjectFactory selhání najít objekt pro vytváření tříd definovaný v knihovně DLL rozšíření MFC.

  • AfxDoForAllClasses nefunguje pro žádné třídy v knihovně DLL rozšíření MFC.

  • Standardní databáze MFC, sokety nebo prostředky OLE se nenačtou. Například AfxLoadString(AFX_IDP_SQL_CONNECT_FAIL) vrátí prázdný řetězec, i když běžná knihovna MFC DLL správně používá databázové třídy MFC.

Řešením těchto problémů je vytvoření a export inicializační funkce v knihovně DLL rozšíření MFC, která vytvoří CDynLinkLibrary objekt. Tuto inicializační funkci volejte přesně jednou z každé běžné knihovny MFC DLL, která používá rozšiřující knihovnu DLL knihovny MFC.

Podpora rozhraní MFC OLE, databáze MFC (nebo rozhraní DAO) nebo soketů MFC

Pokud používáte jakoukoli podporu rozhraní MFC OLE, databáze MFC (nebo rozhraní DAO) nebo soketů MFC v běžné knihovně MFC DLL, v uvedeném pořadí, knihovny MFC debug MFC extension MFCOxxD.dllDLL , MFCDxxD.dlla MFCNxxD.dll (kde xx je číslo verze), jsou automaticky propojeny. Volání předdefinované inicializační funkce pro každou knihovnu DLL, kterou používáte:

  • Pro podporu databáze přidejte volání do AfxDbInitModule běžné knihovny MFC DLL ve své CWinApp::InitInstance funkci. Ujistěte se, že k tomuto volání dochází před voláním základní třídy nebo jakýmkoli přidaným kódem, který přistupuje k MFCDxxD.dll. Tato funkce nepřijímá žádné parametry a vrací void.

  • Pro podporu OLE přidejte volání do AfxOleInitModule běžné knihovny MFC DLL, která je její CWinApp::InitInstance funkcí. Funkce COleControlModule::InitInstance už voláAfxOleInitModule, takže pokud vytváříte ovládací prvek OLE a používáte COleControlModule, neměli byste toto volání přidávat .AfxOleInitModule

  • Pro podporu soketů přidejte volání do AfxNetInitModule běžné knihovny MFC DLL v CWinApp::InitInstancesouboru .

Vydané buildy knihoven MFC DLL a aplikací nepoužívají samostatné knihovny DLL pro podporu databáze, soketů nebo OLE. Je však bezpečné volat tyto inicializační funkce v režimu vydání.

CDynLinkLibrary – objekty

Během každé operace uvedené na začátku tohoto článku musí mfc vyhledat konkrétní hodnotu nebo objekt. Například během deserializace musí MFC prohledávat všechny aktuálně dostupné třídy runtime tak, aby odpovídaly objektům v archivu se správnou třídou runtime.

V rámci těchto hledání mfc prohledá všechny knihovny DLL rozšíření MFC, které se používají, procházením řetězce CDynLinkLibrary objektů. CDynLinkLibrary objekty se automaticky připojují ke řetězu během jejich výstavby a jsou vytvořeny jednotlivými rozšiřujícími knihovnami MFC DLL zase během inicializace. Každý modul (aplikace nebo běžná knihovna MFC DLL) má svůj vlastní řetěz CDynLinkLibrary objektů.

Aby knihovna DLL rozšíření MFC dostala kabel do řetězu CDynLinkLibrary , musí vytvořit CDynLinkLibrary objekt v kontextu každého modulu, který používá rozšiřující knihovnu DLL knihovny MFC. Chcete-li použít knihovnu DLL rozšíření MFC v běžných knihovnách MFC DLL, musí knihovna DLL rozšíření poskytnout exportovanou inicializační funkci, která vytvoří CDynLinkLibrary objekt. Každá běžná knihovna MFC DLL, která používá rozšiřující knihovnu DLL knihovny MFC, musí volat exportovanou inicializační funkci.

Pokud budete používat pouze rozšiřující knihovnu DLL knihovny MFC z aplikace MFC a nikdy z běžné knihovny MFC DLL, stačí vytvořit CDynLinkLibrary objekt ve funkci KNIHOVNY DllMain DLL rozšíření MFC. Je to, co dělá kód knihovny MFC DLL Průvodce knihovnou MFC dll. Při implicitní načítání knihovny DLL rozšíření MFC se DllMain načte a spustí před spuštěním aplikace. Všechny CDynLinkLibrary vytváření jsou připojeny do výchozího řetězu, který knihovna MFC DLL vyhrazuje pro aplikaci MFC.

Je špatné mít v libovolném řetězci více CDynLinkLibrary objektů z jedné knihovny DLL rozšíření MFC. Platí to zejména v případě, že knihovna DLL rozšíření MFC může být dynamicky uvolněna z paměti. Nevolejte funkci inicializace více než jednou z jednoho modulu.

Ukázkový kód

Tento ukázkový kód předpokládá, že běžná knihovna MFC DLL implicitně odkazuje na knihovnu DLL rozšíření MFC. Pokud chcete implicitně propojit knihovnu importu (soubor LIB) knihovny MFC s příponou DLL při sestavování běžné knihovny MFC DLL.

Následující řádky by měly být ve zdroji knihovny DLL rozšíření 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
}

Nezapomeňte exportovat funkci InitYourExtDLL . Můžete ho použít __declspec(dllexport)nebo exportovat do souboru DEF pro knihovnu DLL, jak je znázorněno zde:

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

Přidejte volání InitInstance člena CWinApp-odvozeného objektu v každé běžné MFC DLL pomocí knihovny MFC rozšíření DLL:

// 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;
}

Co chcete udělat?

O čem chcete vědět víc?

Viz také

MFC – rozšiřující knihovny DLL