Używanie bibliotek DLL baz danych, OLE i rozszerzeń MFC gniazd w zwykłych bibliotekach MFC DLL

W przypadku korzystania z biblioteki DLL rozszerzenia MFC ze zwykłej biblioteki MFC DLL, jeśli biblioteka DLL rozszerzenia MFC nie jest podłączna do CDynLinkLibrary łańcucha obiektów zwykłej biblioteki MFC DLL, może wystąpić co najmniej jeden powiązany problem. Ponieważ wersje debugowania bazy danych MFC, ole i gniazd obsługują biblioteki DLL są implementowane jako biblioteki DLL rozszerzeń MFC, mogą wystąpić podobne problemy, jeśli używasz tych funkcji MFC, nawet jeśli nie używasz jawnie żadnych bibliotek DLL rozszerzeń MFC. Niektóre objawy to:

  • Podczas próby deserializacji obiektu typu klasy zdefiniowanej w dll rozszerzenia MFC komunikat "Ostrzeżenie: Nie można załadować klasy CYourClass z archiwum. Klasa nie jest zdefiniowana", pojawia się w oknie debugowania TRACE, a obiekt nie może serializować.

  • Może zostać zgłoszony wyjątek wskazujący nieprawidłową klasę.

  • Nie można załadować zasobów przechowywanych w pliku DLL rozszerzenia MFC, ponieważ AfxFindResourceHandle zwraca NULL lub niepoprawne dojście zasobów.

  • DllGetClassObjectfunkcje składowe , DllCanUnloadNowi , i COleObjectFactoryUpdateRegistryRevokeRevokeAllRegisterAll , nie mogą zlokalizować fabryki klas zdefiniowanej w dll rozszerzenia MFC.

  • AfxDoForAllClasses nie działa w przypadku żadnych klas w dll rozszerzenia MFC.

  • Nie można załadować standardowej bazy danych, gniazd lub zasobów OLE MFC. Na przykład AfxLoadString(AFX_IDP_SQL_CONNECT_FAIL) zwraca pusty ciąg, nawet jeśli zwykła biblioteka MFC DLL prawidłowo używa klas bazy danych MFC.

Rozwiązaniem tych problemów jest utworzenie i wyeksportowanie funkcji inicjowania w bibliotece DLL rozszerzenia MFC, która tworzy CDynLinkLibrary obiekt. Wywołaj tę funkcję inicjowania dokładnie raz z każdej regularnej biblioteki MFC DLL, która używa biblioteki DLL rozszerzenia MFC.

Obsługa gniazd MFC OLE, MFC Database (lub DAO) lub MFC Sockets

Jeśli używasz dowolnych bibliotek MFC OLE, MFC Database (lub DAO) lub MFC Sockets w zwykłej biblioteki MFC DLL, odpowiednio, bibliotekI MFCOxxD.dllDLL debugowania MFC MFC , MFCDxxD.dlli MFCNxxD.dll (gdzie xx jest numerem wersji) są połączone automatycznie. Wywołaj wstępnie zdefiniowaną funkcję inicjowania dla każdej używanej biblioteki DLL:

  • Aby uzyskać obsługę bazy danych, dodaj wywołanie do AfxDbInitModule regularnej biblioteki MFC DLL w swojej CWinApp::InitInstance funkcji. Upewnij się, że to wywołanie ma miejsce przed wywołaniem klasy bazowej lub dodanym kodem, który uzyskuje dostęp do klasy MFCDxxD.dll. Ta funkcja nie przyjmuje parametrów i zwraca wartość void.

  • Aby uzyskać obsługę ole, dodaj wywołanie do AfxOleInitModule zwykłej biblioteki MFC DLL, która jest jego CWinApp::InitInstance funkcją. Funkcja COleControlModule::InitInstance wywołuje już wywołanie AfxOleInitModule , więc jeśli tworzysz kontrolkę OLE i używasz COleControlModulemetody , nie należy dodawać tego wywołania do AfxOleInitModulemetody .

  • W przypadku obsługi gniazd dodaj wywołanie do AfxNetInitModule regularnej biblioteki MFC DLL w pliku CWinApp::InitInstance.

Kompilacje wersji bibliotek DLL MFC i aplikacji nie używają oddzielnych bibliotek DLL dla bazy danych, gniazd ani obsługi ole. Można jednak bezpiecznie wywołać te funkcje inicjowania w trybie wydania.

Obiekty CDynLinkLibrary

Podczas każdej operacji wymienionej na początku tego artykułu MFC musi wyszukać określoną wartość lub obiekt. Na przykład podczas deserializacji MFC musi przeszukiwać wszystkie obecnie dostępne klasy czasu wykonywania, aby dopasować obiekty w archiwum z odpowiednią klasą czasu wykonywania.

W ramach tych wyszukiwań MFC skanuje wszystkie biblioteki DLL rozszerzeń MFC używane przez przejście łańcucha CDynLinkLibrary obiektów. CDynLinkLibrary obiekty są dołączane automatycznie do łańcucha podczas ich budowy i są tworzone przez każdą bibliotekę DLL rozszerzenia MFC z kolei podczas inicjowania. Każdy moduł (aplikacja lub zwykła biblioteka MFC DLL) ma własny łańcuch CDynLinkLibrary obiektów.

Aby biblioteka DLL rozszerzenia MFC była podłączana do CDynLinkLibrary łańcucha, musi utworzyć CDynLinkLibrary obiekt w kontekście każdego modułu korzystającego z biblioteki DLL rozszerzenia MFC. Aby użyć biblioteki DLL rozszerzenia MFC w zwykłych bibliotekach DLL MFC, biblioteka DLL rozszerzenia musi udostępnić wyeksportowaną funkcję inicjowania, która tworzy CDynLinkLibrary obiekt. Każda zwykła biblioteka MFC DLL korzystająca z biblioteki DLL rozszerzenia MFC musi wywoływać wyeksportowaną funkcję inicjowania.

Jeśli używasz biblioteki DLL rozszerzenia MFC tylko z aplikacji MFC i nigdy nie będziesz używać zwykłej biblioteki MFC DLL, wystarczy utworzyć CDynLinkLibrary obiekt w funkcji DLL DllMain rozszerzenia MFC. To właśnie robi kod biblioteki DLL MFC Kreatora MFC rozszerzenia MFC. Podczas ładowania niejawnie DllMain biblioteki DLL rozszerzenia MFC ładuje się i wykonuje przed uruchomieniem aplikacji. Wszystkie CDynLinkLibrary tworzenie są połączone z domyślnym łańcuchem, który biblioteka MFC DLL rezerwuje dla aplikacji MFC.

Jest to zły pomysł, aby mieć wiele CDynLinkLibrary obiektów z jednej biblioteki DLL rozszerzenia MFC w jednym łańcuchu. Jest to szczególnie istotne, jeśli biblioteka DLL rozszerzenia MFC może być dynamicznie zwalniana z pamięci. Nie należy wywoływać funkcji inicjowania więcej niż raz z jednego modułu.

Przykładowy kod

W tym przykładowym kodzie przyjęto założenie, że regularna biblioteka MFC DLL niejawnie łączy się z biblioteką DLL rozszerzenia MFC. Aby połączyć niejawnie, połącz się z biblioteką importu (plik LIB) biblioteki DLL rozszerzenia MFC podczas kompilowania regularnej biblioteki MFC DLL.

Następujące wiersze powinny znajdować się w źródle biblioteki DLL rozszerzenia 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
}

Pamiętaj, aby wyeksportować funkcję InitYourExtDLL . Możesz użyć polecenia __declspec(dllexport)lub wyeksportować go w pliku DEF dla biblioteki DLL, jak pokazano poniżej:

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

Dodaj wywołanie elementu InitInstance członkowskiego -pochodnego CWinAppobiektu w każdej regularnej biblioteki MFC DLL przy użyciu biblioteki DLL rozszerzenia 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;
}

Co chcesz zrobić?

Co chcesz dowiedzieć się więcej?

Zobacz też

Biblioteki DLL rozszerzeń MFC