Usando o banco de dados OLE e DLLs de extensão de Sockets DLLs normais
Ao usar uma extensão DLL a partir de uma DLL regular, se a extensão DLL não conectada para o CDynLinkLibrary cadeia de objetos da DLL regular, você poderá enfrentar um ou mais de um conjunto de problemas relacionados. Porque as versões de depuração do banco de dados do MFC, OLE e soquetes suportam DLLs são implementadas como DLLs de extensão, você poderá ver problemas semelhantes, se você estiver usando esses MFC recursos, mesmo se você não estiver explicitamente usando qualquer uma das suas próprias DLLs de extensão. Estes são alguns sintomas:
Ao tentar desserializar um objeto de um tipo de classe definidos na extensão DLL, a mensagem "Aviso: Não é possível carregar o CYourClass de arquivamento. Classe não definida". é exibido na janela de rastreamento de depuração e o objeto falhar para serializar.
Pode ser lançada uma exceção, indicando a classe incorreta.
Recursos armazenados na DLL de extensão falharem ao carregar porque AfxFindResourceHandle retorna Nulo ou um identificador de recurso incorreto.
DllGetClassObject, DllCanUnloadNowe o UpdateRegistry, Revoke, RevokeAll, e RegisterAll funções de membro de COleObjectFactory Falha ao localizar uma fábrica de classes definida na extensão DLL.
AfxDoForAllClassesnão funciona para qualquer classe na extensão DLL.
Banco de dados padrão do MFC, sockets ou recursos OLE falham ao carregar. Por exemplo, AfxLoadString(AFX_IDP_SQL_CONNECT_FAIL) retorna uma seqüência vazia, mesmo quando a DLL regular adequadamente está usando as classes de banco de dados do MFC.
A solução para esses problemas é criar e exportar uma função de inicialização na extensão DLL que cria uma CDynLinkLibrary objeto. Chame essa função de inicialização exatamente uma vez a partir de cada DLL regular que usa a extensão DLL.
MFC OLE, o banco de dados MFC (ou DAO), ou o suporte de soquetes do MFC
Se você estiver usando qualquer MFC OLE, banco de dados MFC (ou DAO) ou soquetes do MFC suporte na sua DLL regular, respectivamente, a extensão do MFC depurar DLLs MFCOxxD.dll, MFCDxxD.dll e MFCNxxD.dll (onde xx é o número de versão) são vinculados automaticamente. Você deve chamar uma função de inicialização predefinidas para cada uma dessas DLLs que você está usando.
Para obter suporte de banco de dados, adicione uma chamada para AfxDbInitModule a sua DLL regular CWinApp::InitInstance função. Certificar-se de que esta chamada ocorre antes de qualquer chamada de classe base ou nenhum adicionado o código que acessa o MFCDxxD.dll. Esta função sem parâmetros e retorna void.
Para obter suporte OLE, adicione uma chamada para AfxOleInitModule a sua DLL regular CWinApp::InitInstance. Observe que o colecontrolmodule initinstance chamadas de função AfxOleInitModule já, portanto, se você estiver criando um controle OLE e estiver usando COleControlModule, você não deve adicionar essa chamada para AfxOleInitModule.
Para obter suporte de soquetes de segurança, adicione uma chamada para AfxNetInitModule a sua DLL regular CWinApp::InitInstance.
Observe que libere compilações do MFC DLLs e aplicativos não usarem DLLs separadas para o banco de dados, soquetes, ou suporte a OLE. No entanto, é seguro chamar essas funções de inicialização no modo de versão.
Objetos de CDynLinkLibrary
Durante cada uma das operações que mencionei no início deste tópico, o MFC precisa procurar um objeto ou o valor desejado. Por exemplo, durante a desserialização, MFC precisa pesquisar em todas as classes de tempo de execução disponíveis atualmente para coincidir com os objetos no arquivamento com sua classe de tempo de execução adequada.
Como parte dessas pesquisas, MFC examina todas as DLLs de extensão em uso percorrendo uma cadeia de CDynLinkLibrary objetos. CDynLinkLibrary objetos anexar automaticamente uma cadeia durante sua construção e são criados por cada DLL de extensão por sua vez durante a inicialização. Além disso, cada módulo (aplicativo ou DLL regular) tem sua própria cadeia de CDynLinkLibrary objetos.
Para uma extensão DLL para a rede com fio em um CDynLinkLibrary cadeia, ele deve criar um CDynLinkLibrary o objeto no contexto de cada módulo que usa a extensão DLL. Portanto, se uma extensão DLL a ser usado em DLLs normais, ele deverá fornecer uma função de inicialização exportada cria um CDynLinkLibrary objeto. Cada DLL regular que usa a extensão DLL deve chamar a função de inicialização exportada.
Se uma extensão DLL somente for utilizado um aplicativo MFC (. exe) e nunca de uma DLL regular, é suficiente para criar o CDynLinkLibrary a DLL de extensão objeto DllMain. Este é o que faz o código da DLL de extensão de Assistente de DLL da MFC. Ao carregar uma DLL de extensão implicitamente, DllMain carrega e executa antes do aplicativo nunca é iniciado. Qualquer CDynLinkLibrary criações são conectadas em uma cadeia de padrão que a DLL da MFC reserva para um aplicativo MFC.
Observe que é uma boa idéia ter vários CDynLinkLibrary os objetos de uma DLL de extensão em qualquer uma cadeia, especialmente se a DLL de extensão será dinamicamente descarregada da memória. Não chame a função de inicialização mais de uma vez a partir de um módulo qualquer.
Sample Code
O código de exemplo pressupõe que o normal. DLL é implicitamente vinculando a DLL de extensão. Para fazer isso, vinculando a biblioteca de importação da DLL de extensão (. lib) ao criar a DLL regular.
As seguintes linhas devem estar na origem da extensão DLL:
// 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
}
Certifique-se de exportar o InitYourExtDLL função. Isso pode ser feito usando __declspec(dllexport) ou no arquivo. def da DLL da seguinte maneira:
// YourExtDLL.Def:
LIBRARY YOUREXTDLL
CODE PRELOAD MOVEABLE DISCARDABLE
DATA PRELOAD SINGLE
EXPORTS
InitYourExtDLL
Adicione uma chamada para o InitInstance membro da CWinApp-derivado do objeto em cada DLL regular usando a extensão 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 DLL initializing\n");
// wire any extension DLLs into CDynLinkLibrary chain
InitYourExtDLL();
return TRUE;
}