TN011. Использование MFC как часть библиотеки DLL

это примечание описывает обычные библиотеки dll mfc, которые позволяют использовать библиотеку mfc в составе Windows библиотеки динамической компоновки (DLL). предполагается, что вы знакомы с Windows библиотеками dll и как их создавать. Дополнительные сведения о библиотеках DLL расширения MFC, в которых можно создавать расширения для библиотеки MFC, см. в статье DLL-версия MFC.

Интерфейсы DLL

обычные библиотеки DLL MFC предполагают, что интерфейсы между приложением и библиотекой DLL указываются в функциях, похожих на C, или в явно экспортированных классах. Не удается экспортировать интерфейсы классов MFC.

Если и библиотека DLL, и приложение хотят использовать MFC, то оба варианта могут либо использовать общую версию библиотек MFC, либо статически связать их с копией библиотек. Приложение и библиотека DLL могут использовать одну из стандартных версий библиотеки MFC.

обычные библиотеки DLL MFC имеют несколько преимуществ.

  • Приложение, использующее библиотеку DLL, не должно использовать MFC и не обязательно должно быть приложением Visual C++.

  • С помощью регулярных библиотек MFC, которые статически связываются с MFC, размер библиотеки DLL зависит только от используемых и связанных подпрограмм среды выполнения MFC и C.

  • Благодаря обычным библиотекам DLL MFC, динамически связываемым с MFC, экономия в памяти от использования общей версии MFC может быть значительной. Однако необходимо распространять общие библиотеки DLL,версию>.dll MFC < иверсию> мсввкрт <.dll с библиотекой DLL.

  • Структура DLL не зависит от реализации классов. Структура библиотек DLL экспортирует только необходимые API-интерфейсы. В результате, если реализация изменяется, стандартные библиотеки DLL MFC остаются действительными.

  • С помощью регулярных библиотек MFC, которые статически связываются с MFC, если и библиотека DLL, и приложение используют MFC, нет проблем с приложением, которым требуется другая версия MFC, чем у библиотеки DLL, или наоборот. Так как библиотека MFC связана статически с каждой библиотекой DLL или EXE, нет вопросов о том, какая версия имеется.

Ограничения API

Некоторые функции MFC не применяются к версии библиотеки DLL из-за технических ограничений или из-за того, что эти службы обычно предоставляются приложением. В текущей версии MFC единственной неприменимой функцией является CWinApp::SetDialogBkColor .

Создание библиотеки DLL

При компиляции регулярных библиотек DLL MFC, которые статически связываются с MFC, символы _USRDLL и _WINDLL должны быть определены. Код библиотеки DLL также должен быть скомпилирован с помощью следующих параметров компилятора:

  • /D_WINDLL означает, что компиляция предназначена для библиотеки DLL

  • /D_USRDLL указывает, что вы создаете обычную БИБЛИОТЕКУ DLL MFC

Необходимо также определить эти символы и использовать эти параметры компилятора при компиляции регулярных библиотек DLL MFC, которые динамически связываются с MFC. Кроме того, символ _AFXDLL должен быть определен, и код DLL должен быть скомпилирован с помощью:

  • /D_AFXDLL указывает, что создается обычная библиотека DLL MFC, которая динамически связывается с MFC.

Интерфейсы (API) между приложением и библиотекой DLL должны быть экспортированы явным образом. Рекомендуется определить интерфейсы с низкой пропускной способностью и использовать только интерфейсы C, если это возможно. Прямые интерфейсы C проще в обслуживании, чем более сложные классы C++.

Разместите API в отдельном заголовке, который можно включать в файлы C и C++. Пример см. в заголовке снимке экрана. h в образце примера " дополнительные понятия MFC". Чтобы экспортировать функции, введите их в EXPORTS раздел файла определения модуля (. DEF) или включить __declspec(dllexport) в определения функций. Используйте __declspec(dllimport) для импорта этих функций в исполняемый файл клиента.

Необходимо добавить AFX_MANAGE_STATE макрос в начало всех экспортированных функций в обычных библиотеках DLL MFC, которые динамически связываются с MFC. Этот макрос задает текущее состояние модуля для библиотеки DLL. Чтобы использовать этот макрос, добавьте следующую строку кода в начало функций, экспортированных из библиотеки DLL:

AFX_MANAGE_STATE(AfxGetStaticModuleState( ))

WinMain- > DllMain

Библиотека MFC определяет стандартную точку входа Win32 DllMain , которая инициализирует производный объект CWinApp как в обычном приложении MFC. Поместите всю инициализацию библиотеки DLL в метод InitInstance , как в обычном приложении MFC.

Обратите внимание, что механизм CWinApp:: Run не применяется к библиотеке DLL, так как приложение владеет основным конвейером сообщений. Если в библиотеке DLL отображаются немодальные диалоговые окна или имеется главное окно фрейма, то основной конвейер сообщений приложения должен вызвать подпрограммы, экспортируемые из библиотеки DLL, вызывающие CWinApp::P ретранслатемессаже.

См. пример DLLScreenCap для использования этой функции.

DllMainФункция, предоставляемая библиотекой MFC, будет вызывать метод CWinApp:: ExitInstance класса, производного от CWinApp , перед выгрузкой библиотеки DLL.

Связывание библиотеки DLL

С помощью регулярных библиотек MFC, которые статически связываются с MFC, необходимо связать библиотеку DLL с Нафксквд. lib или Нафкскв. lib и версией среды выполнения C с именем LIBCMT. lib. Эти библиотеки предварительно созданы и могут быть установлены путем указания их при запуске программы установки Visual C++.

Пример кода

Полный пример см. в образце программы MFC с примерами программ для опытных концепций. В этом примере обратите внимание на несколько интересных моментов.

  • Флаги компилятора библиотеки DLL и приложения отличаются.

  • Линии связи и. DEF-файлы для библиотеки DLL и для приложения различаются.

  • Приложение, использующее библиотеку DLL, не обязательно должно находиться в C++.

  • Интерфейс между приложением и библиотекой DLL — это API, который может использоваться C или C++ и экспортирован с помощью DLLScreenCap. def.

В следующем примере показан API, определенный в обычной библиотеке DLL MFC, которая статически связывается с MFC. В этом примере объявление заключено в extern "C" { } блок для пользователей C++. Это имеет несколько преимуществ. Во-первых, он делает интерфейсы API DLL пригодными для использования в клиентских приложениях, не относящихся к C + +. Во-вторых, это сокращает затраты DLL, так как искажение имен C++ не будет применяться к экспортированному имени. Наконец, это упрощает явное добавление в. DEF-файл (для экспорта по порядковому номеру) без необходимости беспокоиться о искажении имен.

#ifdef __cplusplus
extern "C" {
#endif  /* __cplusplus */

struct TracerData
{
    BOOL bEnabled;
    UINT flags;
};

BOOL PromptTraceFlags(TracerData FAR* lpData);

#ifdef __cplusplus
}
#endif

Структуры, используемые API, не являются производными от классов MFC и определены в заголовке API. Это уменьшает сложность интерфейса между библиотекой DLL и приложением и делает библиотеку DLL доступной для программ C.

См. также раздел

Технические примечания по номеру
Технические примечания по категориям