Partilhar via


Uso de DLLs de extensão MFC para banco de dados, OLE e soquetes em DLLs MFC regulares

Ao usar uma DLL de extensão MFC de uma DLL MFC regular, se a DLL de extensão MFC não estiver conectada CDynLinkLibrary à cadeia de objetos da DLL MFC regular, você poderá ter um ou mais problemas relacionados. Como as versões de depuração do banco de dados MFC, OLE e DLLs de suporte a soquetes são implementadas como DLLs de extensão MFC, você pode ver problemas semelhantes se estiver usando esses recursos MFC, mesmo se você não estiver usando explicitamente qualquer uma de suas próprias DLLs de extensão MFC. Alguns sintomas são:

  • Ao tentar desserializar um objeto de um tipo de classe definida na extensão MFC DLL, a mensagem "Aviso: Não é possível carregar CYourClass do arquivo. Class not defined." aparece na janela de depuração TRACE e o objeto não consegue serializar.

  • Uma exceção indicando classe ruim pode ser lançada.

  • Os recursos armazenados na DLL de extensão MFC não são carregados porque AfxFindResourceHandle retorna NULL ou um identificador de recurso incorreto.

  • DllGetClassObject, DllCanUnloadNow e as funções membro UpdateRegistry, Revoke, RevokeAll, e RegisterAll de COleObjectFactory falham ao localizar uma fábrica de classes definida numa DLL de extensão MFC.

  • AfxDoForAllClasses não funciona para nenhuma classe na DLL de extensão MFC.

  • Banco de dados MFC padrão, soquetes ou recursos OLE não são carregados. Por exemplo, AfxLoadString(AFX_IDP_SQL_CONNECT_FAIL) retorna uma cadeia de caracteres vazia, mesmo quando a DLL MFC regular está usando corretamente as classes de banco de dados MFC.

A solução para esses problemas é criar e exportar uma função de inicialização na DLL de extensão MFC que cria um CDynLinkLibrary objeto. Chame esta função de inicialização exatamente uma vez em cada DLL MFC regular que utiliza a DLL de extensão MFC.

MFC OLE, MFC Database (ou DAO) ou Suporte de Sockets MFC

Se estiver a utilizar suporte para MFC OLE, MFC Database (ou DAO) ou MFC Sockets na sua DLL MFC regular, as DLLs de extensão MFC de depuração MFCOxxD.dll, MFCDxxD.dll e MFCNxxD.dll (onde xx é o número da versão) serão vinculadas automaticamente. Chame uma função de inicialização predefinida para cada uma das DLLs que você está usando:

  • Para suporte de banco de dados, adicione uma chamada para AfxDbInitModule na função CWinApp::InitInstance da sua DLL MFC regular. Certifique-se de que esta chamada ocorre antes de qualquer chamada de classe base ou qualquer código adicionado que aceda ao MFCDxxD.dll. Esta função não usa parâmetros e retorna void.

  • Para o suporte do OLE, adicione uma chamada para o seu DLL regular do MFC na sua função AfxOleInitModule. A função COleControlModule::InitInstance já chama AfxOleInitModule, portanto, se estiver a criar um controlo OLE e usar COleControlModule, não deve adicionar esta chamada a AfxOleInitModule.

  • Para suporte a Sockets, adicione uma chamada para AfxNetInitModule na sua DLL MFC regular em CWinApp::InitInstance.

Compilações de lançamento de DLLs MFC e aplicações não utilizam DLLs separadas para suporte a base de dados, sockets ou OLE. No entanto, é seguro chamar essas funções de inicialização no modo de lançamento.

Objetos CDynLinkLibrary

Durante cada operação mencionada no início deste artigo, o MFC precisa procurar um determinado valor ou objeto. Por exemplo, durante a desserialização, o MFC precisa pesquisar todas as classes de execução atualmente disponíveis para associar objetos no arquivo com a sua classe de execução adequada.

Como parte dessas pesquisas, o MFC examina todas as DLLs de extensão MFC em uso, percorrendo uma cadeia de CDynLinkLibrary objetos. CDynLinkLibrary os objetos se conectam automaticamente a uma cadeia durante sua construção e são criados por cada DLL de extensão MFC por sua vez durante a inicialização. Cada módulo (aplicativo ou DLL MFC regular) tem sua própria cadeia de CDynLinkLibrary objetos.

Para que uma DLL de extensão MFC seja conectada a uma CDynLinkLibrary cadeia, ela deve criar um CDynLinkLibrary objeto no contexto de cada módulo que usa a DLL de extensão MFC. Para usar uma DLL de extensão MFC em DLLs MFC regulares, a DLL de extensão deve fornecer uma função de inicialização exportada que cria um CDynLinkLibrary objeto. Cada DLL MFC regular que usa a DLL de extensão MFC deve chamar a função de inicialização exportada.

Caso utilize apenas uma DLL de extensão MFC a partir de uma aplicação MFC, e nunca a partir de uma DLL MFC regular, então é suficiente criar o objeto CDynLinkLibrary na função DllMain da DLL de extensão MFC. É o que o código da extensão DLL do Assistente MFC faz. Ao carregar uma DLL de extensão MFC implicitamente, DllMain carrega e executa antes que o aplicativo seja iniciado. Todas CDynLinkLibrary as criações são conectadas em uma cadeia padrão que a DLL MFC reserva para um aplicativo MFC.

É uma má ideia ter vários CDynLinkLibrary objetos de uma DLL de extensão MFC em uma única cadeia. É especialmente verdadeiro se a DLL da extensão MFC pode ser descarregada dinamicamente da memória. Não chame a função de inicialização mais de uma vez a partir de qualquer módulo.

Código de Exemplo

Este código de exemplo pressupõe que a DLL MFC regular implicitamente se vincula à DLL de extensão MFC. Para vincular implicitamente, vincule à biblioteca de importação (ficheiro LIB) da DLL de extensão MFC ao criar a DLL MFC regular.

As seguintes linhas devem estar no código-fonte da DLL de extensão 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
}

Certifique-se de exportar a função InitYourExtDLL . Você pode usar __declspec(dllexport)ou exportá-lo no arquivo DEF para sua DLL, conforme mostrado aqui:

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

Adicione uma chamada para o membro do objeto derivado InitInstance em cada DLL MFC regular, usando a DLL de extensão 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;
}

O que pretende fazer?

Sobre o que quer saber mais?

Ver também

DLLs de extensão MFC