Инициализация библиотек расширения
Поскольку в библиотеках расширения, в отличие от обычных библиотек DLL, не используется производный от CWinApp объект, следует добавить код инициализации и завершения в функцию DllMain, созданную с помощью мастера DLL MFC.
C помощью мастера автоматически создается следующий код библиотеки расширения. В приведенном ниже коде вместо PROJNAME следует использовать имя создаваемого проекта.
#include "stdafx.h"
#include <afxdllx.h>
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
static AFX_EXTENSION_MODULE PROJNAMEDLL = { NULL, NULL };
extern "C" int APIENTRY
DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
{
if (dwReason == DLL_PROCESS_ATTACH)
{
TRACE0("PROJNAME.DLL Initializing!\n");
// Extension DLL one-time initialization
AfxInitExtensionModule(PROJNAMEDLL,
hInstance);
// Insert this DLL into the resource chain
new CDynLinkLibrary(Dll3DLL);
}
else if (dwReason == DLL_PROCESS_DETACH)
{
TRACE0("PROJNAME.DLL Terminating!\n");
}
return 1; // ok
}
За счет создания нового объекта CDynLinkLibrary во время инициализации обеспечивается экспорт объектов CRuntimeClass или ресурсов из библиотеки расширения в клиентское приложение.
Если предполагается использование библиотеки расширения в одной или нескольких обычных библиотеках DLL, необходимо экспортировать функцию, с помощью которой создается объект CDynLinkLibrary. Эту функцию необходимо вызывать в каждой из обычных библиотек, в которых используется библиотека расширения. Чтобы использовать классы и функции, экспортированные из библиотеки расширения, необходимо вызвать эту функцию инициализации в функции-члене InitInstance объекта, производного от класса CWinApp обычной библиотеки DLL.
В функции DllMain, автоматически создаваемой с помощью мастера DLL MFC, при обращении к функции AfxInitExtensionModule регистрируются классы времени выполнения модуля (структуры CRuntimeClass), а также производства объектов (объекты COleObjectFactory), которые используются при создании объекта CDynLinkLibrary. Проверьте значение, возвращаемое функцией AfxInitExtensionModule. Если функция AfxInitExtensionModule возвращает нулевое значение, в функции DllMain также следует возвратить нулевое значение.
Если библиотека расширения явно связана с исполняемым файлом (то есть в исполняемом файле вызывается функция AfxLoadLibrary для связывания с библиотекой DLL), следует добавить вызов функции AfxTermExtensionModule со значением DLL_PROCESS_DETACH. Эта функция используется в MFC для очистки библиотеки расширения после отсоединения от нее всех процессов (выполняется при завершении процесса или выгрузке библиотеки DLL с помощью функции AfxFreeLibrary). В случае неявного связывания библиотеки расширения с приложением вызывать функцию AfxTermExtensionModule не требуется.
В приложениях, явно связанных с библиотеками расширения, при освобождении библиотеки следует вызвать функцию AfxTermExtensionModule. Если в таком приложении используется несколько потоков, следует вызвать функции AfxLoadLibrary и AfxFreeLibrary (вместо функций Win32 LoadLibrary и FreeLibrary). При использовании функций AfxLoadLibrary и AfxFreeLibrary гарантируется, что выполнение кода запуска и завершения работы при загрузке и выгрузке библиотеки расширения, не приведет к повреждению глобального состояния MFC.
Поскольку на момент вызова функции DllMain инициализация библиотеки MFCx0.dll полностью завершается, можно выделить память и вызвать функции MFC в функции DllMain (в отличие от 16-разрядной версии MFC).
В библиотеках расширения многопоточность реализуется за счет обработки значений DLL_THREAD_ATTACH и DLL_THREAD_DETACH функции DllMain. Эти значения передаются в функцию DllMain в случае присоединения потоков к библиотеке DLL и отсоединения от нее соответственно. Чтобы обеспечить хранение в библиотеке DLL индексов локальной памяти потока (TLS) для каждого присоединенного к ней потока, вызовите функцию TlsAlloc в процессе присоединения библиотеки DLL.
Обратите внимание, что в файле заголовка Afxdllx.h содержатся специальные определения для структур, используемых в библиотеках расширения, например AFX_EXTENSION_MODULE и CDynLinkLibrary. Этот файл заголовка необходимо включить в библиотеку расширения.
Примечание
Обратите внимание, что в файле Stdafx.h не допускается определение или отмена определения каких-либо макросов _AFX_NO_XXX.Дополнительные сведения см. в статье базы знаний "PRB. Проблемы, возникающие при определении _AFX_NO_XXX" (на английском языке, ИД статьи — 140751).Статьи базы знаний можно найти в библиотеке MSDN или с http://search.support.microsoft.com/.
Пример функции инициализации, в которой реализуется обработка многопоточности, см. в разделе Использование локальной памяти потока в библиотеке DLL в пакете Windows SDK. Обратите внимание, что в примере используется функция точки входа LibMain, которой следует присвоить имя DllMain, что позволит использовать ее в библиотеках времени выполнения MFC и C.
В примере MFC DLLHUSK показан порядок использования функций инициализации.
Выберите действие.
Дополнительные сведения
Поведение библиотеки времени выполнения языка C и функция _DllMainCRTStartup
Использование библиотек DLL расширения баз данных, OLE и сокетов в обычных библиотеках DLL
Функция точки входа библиотеки динамической компоновки (Windows SDK)