Поделиться через


TN033. Версия библиотеки DLL MFC

Эта заметка описывает, как использовать MFCxx.dll и MFCxxD.DLL (где x является номером версии MFC) библиотеки динамической компоновки (DLL) с приложениями и библиотеками DLL расширения MFC. Дополнительные сведения о библиотеках DLL обычной см. в разделе Использование MFC в составе dll-библиотеки.

Это техническое примечание 3 рассматриваются два библиотеки DLL. Последние 2 для опытных пользователей.

  • Как при построении библиотеки DLL расширения MFC

  • О построении приложения MFC, которая использует версию библиотеки DLL MFC

  • Как общие библиотеки динамической компоновки MFC реализованы

Если необходимо настроить в построение, библиотеки DLL с MFC, который можно использовать с приложениями этим называется обычной библиотеки (DLL) см. в разделе Техническое примечание 11.

Обзор поддержки MFCxx.dll. Терминология и файлов

Обычная библиотека DLL: Используется обычная библиотека DLL для построения изолированного DLL с помощью некоторые классы MFC. Интерфейсы через границу App/DLL интерфейсы «C», и клиентское приложение не должно быть приложением MFC.

Это версия, поддерживаемая в библиотеке DLL MFC 1.0. Оно описана в Техническое примечание 11 и в расширенном примере MFC DLLScreenCap понятий.

Примечание

Начиная с версии 4.0 Visual C++, термин USRDLL устарел и заменен обычной библиотеки DLL, статически скомпонована с MFC.Можно также построение обычной библиотеки DLL, динамически связываемой с MFC.

MFC (3.0 и выше) поддерживает обычную библиотеку DLL с полностью новой функцией, включая OLE и классы базы данных.

AFXDLL: Это также называется общая версия библиотеки MFC. Это новая поддержка библиотеки DLL с MFC в 2.0. Сама библиотека MFC в нескольких библиотек DLL (описанный ниже) и клиентское приложение или DLL динамически связываемых библиотек DLL, от которых он требует. Интерфейсы через границу служб или DLL интерфейсы класса C ++/MFC. Клиентское приложение ДОЛЖНО быть приложением MFC. Это поддерживает все функции MFC 3.0 (исключение: ЮНИКОДА не поддерживается для классов базы данных).

Примечание

Начиная с версии Visual C++ 4.0 C, этот вид библиотек DLL называется «библиотеки DLL расширения».

Эта заметка будет использовать MFCxx.dll для обращения ко всему набору библиотек DLL MFC, которая включает:

  • Отладка: Совокупное MFCxxD.DLL () и MFCSxxD.LIB (статический).

  • Выпуск: Совокупное (MFCxx.dll) и MFCSxx.LIB (статический).

  • Юникод отладки: Совокупное MFCxxUD.DLL () и MFCSxxD.LIB (статический).

  • Выпуск юникода: Совокупное MFCxxU.DLL () и MFCSxxU.LIB (статический).

Примечание

Библиотеки MFCSxx [U] [D] .LIB используются вместе с библиотекой DLL MFC поделеннсяыми.Эти библиотеки содержат код, необходимый для статического связывания в приложение или библиотеку DLL.

Ссылки на соответствующие приложения библиотеки импорта.

  • Отладка: MFCxxD.LIB

  • Выпуск: MFCxx.LIB

  • Юникод отладки: MFCxxUD.LIB

  • Выпуск юникода: MFCxxU.LIB

«Библиотеки DLL расширения MFC» библиотека DLL строится от MFCxx.dll (или других общих MFC DLL). Здесь архитектура MFC компонент в дело. При наследовании от класса полезный MFC, или построения на другой MFC — это набор элементов, можно разместить его в библиотеку DLL. Что DLL использует MFCxx.dll, а также как клиентское приложение. Это позволяет многократно используемых классов конечного, повторно базовые классы и повторно представление, классы документа.

Преимущества и недостатки

Поэтому следует использовать общедоступную версию MFC?

  • С помощью общей библиотеки может привести к небольших приложениях (минимальное приложение, которое использует большую часть библиотеки MFC, чем 10K).

  • Общая версия MFC поддерживает библиотеки DLL расширения MFC и обычной библиотеки DLL.

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

Поэтому не следует использовать общедоступную версию MFC:

  • Выпуск приложений, использующих общую библиотеку требуется грузите библиотека MFCxx.dll (и других) с программой. MFCxx.dll свободно распространяемые наравне с библиотекой DLL, но при этом следует установить библиотеку DLL в программе установки. Кроме того, необходимо предоставить MSVCRTxx.DLL, содержащий библиотеку C# выполнения, которая используется как программой, так и самими библиотеками MFC DLL.

Создание библиотеки DLL расширения MFC

Библиотеки DLL расширения MFC, содержащий классы и функции библиотеки DLL, написанные для прорисовки функциональность классов MFC. Библиотека DLL расширения MFC использует общие библиотеки DLL MFC точно так, как приложение использует его, учитывая следующее:

  • Процесс построения похож на построение приложения, которое использует общие библиотеки MFC с небольшим дополнительный компилятора и компоновщика.

  • Библиотека DLL расширения MFC не имеет CWinApp- производного класса.

  • Библиотека DLL расширения MFC должен предоставлять специальное DllMain. Предоставляет AppWizard функция DllMain, можно изменить.

  • Библиотека DLL расширения MFC обычно является предоставление процедуру инициализации для создания CDynLinkLibrary, если библиотека DLL расширения хочет экспортировать CRuntimeClass es или ресурсы в приложение. Производный класс CDynLinkLibrary может использоваться, если данные для каждого приложения должны быть поддерживаются библиотекой DLL расширения.

Эти вопросы описаны более подробно ниже. Необходимо также добавить в примере MFC DLLHUSK выдвинутому понятий, поскольку он иллюстрирует:

  • Построение приложений с помощью общие библиотеки. (DLLHUSK.EXE приложение MFC, которая динамически скомпонована с библиотеками MFC, так и другими DLL).

  • Построение библиотеки DLL расширения MFC. (Обратите внимание, что специальные флажки, например _AFXEXT, используемые в построение библиотеки DLL расширения)

  • Пример 2 библиотеки расширения MFC. Он указывает, что базовая структура библиотеки DLL расширения MFC с ограниченными экспортами (TESTDLL1) и других отображает экспортировать все интерфейс класса (TESTDLL2).

И клиентское приложение и любой библиотеке расширения должны использовать одну и ту же версию MFCxx.dll. Необходимо соблюдать соглашение MFC DLL и предоставить и отладки и версия розницы (/release) библиотеки DLL расширения. Это позволяет клиентские программы построения и отладки и конечную версии своих приложений и связывать их с соответствующим отладки или отладочная версия всех библиотек DLL.

Примечание

Поскольку проблемы корежить и экспортировать имени C++ экспортных список товаров из библиотеки расширения могут быть разными между отладки и розничными версиями того же библиотеку DLL и DLL для разных платформ.Розница MFCxx.dll имеет примерно 2000 экспортированных точки входа; отладка MFCxxD.DLL имеет о 3000 экспортировало точки входа.

Эта заметка на управление памятью

Раздел под названием «управлением памятью,» в конце данного технического примечания, описывает реализацию MFCxx.dll с общей версией MFC. Данные необходимо знать для реализации просто библиотека DLL расширения описаны здесь.

MFCxx.dll и все библиотеки DLL расширения, загруженные в адресное пространство клиентского приложения будут использовать тот же распределитель памяти, загрузку ресурсов и другие глобальные состояния MFC «», как если бы они находились в одном приложении. Это значительно, поскольку библиотеки DLL и обычной библиотеки DLL, статически связанным с MFC ведут себя совершенно противоположно; выделение библиотеки DLL осуществляется из собственного пула памяти.

Если библиотека DLL расширения выделяет память, эта память может свободное распределение любыми объектами в приложении. Кроме того, если приложение, использующее общие библиотеки MFC сбой, защита операционной системы будет поддерживать целостность любого другого приложения MFC DLL.

Аналогично другие глобальные состояния MFC «», такие как текущий исполняемый файл для загрузки ресурсов, также совместно используются клиентским самим приложением и всеми библиотеками DLL расширения MFC, так и в файле.

Построение библиотеки DLL расширения

Можно использовать AppWizard создание проекта библиотеки DLL расширения MFC и автоматически создает соответствующие параметры компилятора и компоновщика. Он был также создает функцию DllMain, можно изменить.

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

  • Добавьте /D_AFXEXT в флажкам компилятора. В диалоговом окне свойств проекта, выделите узел C C И C++. Затем выделите категория препроцессора. Добавьте _AFXEXT к полю макросов определение, отделяя каждый из элементов точкой с запятой.

  • Удалите параметр компилятора /Gy. В диалоговом окне свойств проекта, выделите узел C C И C++. Затем выделите категория создания кода. Убедитесь, что «включите компоновку на уровне функций» не позволяет. Это сделает более удобным для экспортирования классов, поскольку компоновщик не удаляет неиспользуемая функции. Если используется исходном проекте построение обычной библиотеки DLL, статически компонуемой с MFC, измените параметр компилятора /MT[d] на /MD[d].

  • Построение библиотеки экспорта с параметром /DLL программе LINK. Это устанавливается при создании нового целевого объекта, определение библиотеку динамической компоновки Win32 в качестве типа целевого объекта.

Изменить файлы заголовка

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

Чтобы сделать это, необходимо убедиться, что каждый из функции-члены отмечен как импортировать или экспортировать соответственно. Это требует специальных объявлений: __declspec(dllexport) и __declspec(dllimport). Если в классы используются клиентскими приложениями, который они должны быть объявлены как __declspec(dllimport). Если сама библиотека расширения выполняется, они должны быть объявлены как __declspec(dllexport). Кроме того, функции, необходимо экспортировать, чтобы клиентские программы связанную с ним во время загрузки.

Чтобы экспортировать для всего класса, используйте AFX_EXT_CLASS в определении класса. Этот макрос определяется структурой как __declspec(dllexport), _AFXDLL и _AFXEXT указаны, но определяется в качестве __declspec(dllimport) при _AFXEXT не определено. _AFXEXT, как описано выше, определяется только при построении библиотеки DLL расширения. Примеры.

class AFX_EXT_CLASS CExampleExport : public CObject
{ ... class definition ... };

Частичный экспорт класса

Иногда может потребоваться экспортировать только отдельные необходимые члены класса. Например, при экспортировании класса, производного от CDialog, возможно, потребуется экспортировать только конструктора и вызов DoModal. Можно экспортировать эти члены с помощью файла .DEF библиотеки DLL, но можно также использовать AFX_EXT_CLASS во многом аналогично на отдельных участниках необходимо экспортировать.

Примеры.

class CExampleDialog : public CDialog
{
public:
   AFX_EXT_CLASS CExampleDialog();
   AFX_EXT_CLASS int DoModal();
   // rest of class definition
   .
   .
   .
};

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

Например, при построении библиотеки расширения макрос DECLARE_DYNAMIC определяется следующим образом:

#define DECLARE_DYNAMIC(class_name) \
protected: \
   static CRuntimeClass* PASCAL _GetBaseClass(); \
   public: \
   static AFX_DATA CRuntimeClass class##class_name; \
   virtual CRuntimeClass* GetRuntimeClass() const; \

Линия, которая инициирует «статическое AFX_DATA» объявляет статический объект внутри класса. Чтобы экспортировать этот класс правильно и получения сведений о среде выполнения из клиента .EXE необходимо экспортировать этот статический объект. Поскольку статический объект объявляется вместе с модификатором AFX_DATA, необходимо определить AFX_DATA в качестве __declspec(dllexport) при построении библиотеки DLL, а также определить в качестве __declspec(dllimport) при построении исполняемого клиентского файла.

, Как описано выше, AFX_EXT_CLASS уже определен таким образом. Необходимо повторно определить AFX_DATA для соответствия объекту AFX_EXT_CLASS в пределах определения класса.

Примеры.

   #undef  AFX_DATA
   #define AFX_DATA AFX_EXT_CLASS
   class CExampleView : public CView
   {
     DECLARE_DYNAMIC()
     // ... class definition ...
   };
   #undef  AFX_DATA
   #define AFX_DATA

MFC всегда использует символ AFX_DATA в элементах данных он определяет внутри его макросов, поэтому этот метод будет работать для всех этих сценариев. Например, он будет работать для DECLARE_MESSAGE_MAP.

Примечание

При экспортировании всего класса, а не отдельно выбранных членов, статические члены данных экспортируются автоматически.

Можно использовать один и тот же метод автоматически экспортировать оператор извлечения CArchive для классов, которые используют макросы DECLARE_SERIAL и IMPLEMENT_SERIAL. Экспортируйте оператор архива должен быть заключен между объявления класса (расположенные в. Файл H) следующим кодом:

#undef AFX_API
#define AFX_API AFX_EXT_CLASS

<your class declarations here>

#undef AFX_API
#define AFX_API

Ограничения директивы _AFXEXT

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

Проблема заключается в том, что в Win32 требуется явно объявлять все данные как __declspec(dllexport), если они должны экспортироваться из данной DLL, и как __declspec(dllimport), если они должны импортироваться из другой DLL. Когда объявляется директива _AFXEXT, заголовочные классы MFC обеспечивают корректность объявления директивы AFX_EXT_CLASS.

Если существует несколько уровней, одиночного символа AFX_EXT_CLASS уже недостаточно, поскольку библиотеки DLL расширения, может экспортировать новые классы, а также импортировать другие классы из другой библиотеки DLL расширения. Чтобы работать с этой проблемой, используйте специальный символ препроцессора, указывает, что при построении библиотеки DLL, и использования библиотеки DLL. Например, есть две библиотеки DLL расширения 2, A.DLL и B.DLL. Они каждый экспортировать некоторые классы в A.H и B.H соответственно. B.DLL используются классы из A.DLL. Их заголовочные файлы выглядят примерно следующим образом:

/* A.H */
#ifdef A_IMPL
   #define CLASS_DECL_A   __declspec(dllexport)
#else
   #define CLASS_DECL_A   __declspec(dllimport)
#endif

class CLASS_DECL_A CExampleA : public CObject
{ ... class definition ... };

/* B.H */
#ifdef B_IMPL
   #define CLASS_DECL_B   __declspec(dllexport)
#else
   #define CLASS_DECL_B   __declspec(dllimport)
#endif

class CLASS_DECL_B CExampleB : public CExampleA
{ ... class definition .. };

При A.DLL создано, оно построено с /D A_IMPL и B.DLL при построении, оно построено с /D B_IMPL. С помощью отдельного символов для каждого библиотеки DLL, CExampleB экспортировано и импортировано CExampleA при построении B.DLL. Экспортировано при построении A.DLL и импортировано CExampleA при использовании B.DLL (или другой клиентом).

Этот тип иерархическое представление не может быть выполнено при использовании встроенных AFX_EXT_CLASS и символы препроцессора _AFXEXT. Вышеописанная техника решает эту проблему способом, отличным от механизм, который используется классами MFC свою библиотеки DLL расширения OLE, базы данных и сети.

Частичный экспорт класса

При этом следует соблюдать осторожность при уход особый не экспортировать весь класс. Необходимо убедиться, что элементы необходимых данных, созданные макросами MFC экспортируются правильно. Это можно сделать, указав AFX_DATA повторно макросу, определенных классов. Так следует поступать всегда, когда класс экспортируется частично.

Примеры.

// A.H
#ifdef A_IMPL
   #define CLASS_DECL_A  _declspec(dllexport)
#else
   #define CLASS_DECL_A  _declspec(dllimport)
   #endif

#undef  AFX_DATA
#define AFX_DATA CLASS_DECL_A

class CExampleA : public CObject
{
   DECLARE_DYNAMIC()
   CLASS_DECL_A int SomeFunction();
   //class definition 
   .
   .
   .
};

#undef AFX_DATA
#define AFX_DATA

DllMain

Точный следующий код необходимо задать в главном файле источника для библиотеки DLL расширения. Он должен располагаться после стандартные включаемые. Обратите внимание, что при использовании AppWizard для создания файлов стартера для библиотеки DLL расширения, он предоставляет DllMain автоматически.

#include "afxdllx.h"

static AFX_EXTENSION_MODULE extensionDLL;

extern "C" int APIENTRY 
DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID)
{
   if (dwReason == DLL_PROCESS_ATTACH)
   {
      // Extension DLL one-time initialization 
      if (!AfxInitExtensionModule(
             extensionDLL, hInstance))
         return 0;

      // TODO: perform other initialization tasks here
   }
   else if (dwReason == DLL_PROCESS_DETACH)
   {
      // Extension DLL per-process termination
      AfxTermExtensionModule(extensionDLL);

          // TODO: perform other cleanup tasks here
   }
   return 1;   // ok
}

Вызов AfxInitExtensionModule регистрируются классы среды выполнения модулей (структуры CRuntimeClass ), а также производства объектов (объекты COleObjectFactory ) для последующего использования, когда объект CDynLinkLibrary будет создан. (Необязательно) вызов AfxTermExtensionModule позволяет MFC в очистке библиотеки DLL расширения, когда каждый процесс окончательно удаляет (это происходит, когда процесс выходы, или при выгрузке библиотеки DLL в результате вызова FreeLibrary ) из библиотеки расширения. Поскольку большинство динамической библиотеки DLL расширения не загружается (как правило, они связаны с помощью их библиотеки импорта), вызов AfxTermExtensionModule обычно не требуется.

Если приложение загружает и освобождает библиотеки DLL расширения динамически необходимо вызвать AfxTermExtensionModule, как показано выше. Также убедитесь в том, что используется AfxLoadLibrary и AfxFreeLibrary (вместо функций Win32 LoadLibrary и FreeLibrary), если приложение использует несколько потоков или если она динамически загружает библиотеку DLL расширения. С помощью AfxLoadLibrary и AfxFreeLibrary гарантирует, что запуска и завершения работы код, который выполняется при загрузке и выгрузке библиотеки DLL расширения не приведет к повреждению глобального состояния MFC.

Файл заголовка AFXDLLX.H содержит специальные определения для структур, используемых в библиотеке расширения, например определение AFX_EXTENSION_MODULE и CDynLinkLibrary.

Глобальный extensionDLL должен быть объявлен как показано. В отличие от 16 разрядную версию MFC, можно выделить память и вызвать функции MFC в течение этого времени, поскольку MFCxx.dll полностью завершается к моменту в DllMain называется.

Общий доступ к ресурсам и классам

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

Экспорт ресурсов осуществляется по списку ресурсов. В каждом приложении однонаправленный список объектов CDynLinkLibrary. При поиске ресурса большинство стандартных реализаций MFC, загружающих ресурсы, сначала в текущем модуле ресурсов (AfxGetResourceHandle), и если найдена проверка список объектов CDynLinkLibrary, пытаясь загрузить запрошенный ресурс.

Динамическое создание объектов C++, данное имя класса C++ аналогичным образом. Механизм десериализации объекта MFC должен иметь всех объектов CRuntimeClass таким образом, чтобы он мог этой динамически создать объект C++ требуемого типа на основе того, что было сохранено ранее.

Если требуется клиентское приложение для использования классов в библиотеке DLL, расширения, DECLARE_SERIAL, то необходимо экспортировать классов, чтобы быть видны клиентскому приложению. Также это делается путем прохода по списку CDynLinkLibrary.

В случае примера MFC расширенного понятий DLLHUSK, список выглядит примерно так:

head ->   DLLHUSK.EXE   - or -   DLLHUSK.EXE
               |                      |
          TESTDLL2.DLL           TESTDLL2.DLL
               |                      |
          TESTDLL1.DLL           TESTDLL1.DLL
               |                      |
               |                      |
            MFC90D.DLL            MFC90.DLL

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

Слияние ресурсы и имена классов всех DLL в пространство имен клиентского приложения имеет недостаток заключается в том, что следует соблюдать осторожность, идентификаторы и имена необходимости. Хотя можно отключить эту функцию не экспортировать или ресурсы или объект CDynLinkLibrary клиентскому приложению. Пример DLLHUSK управляет пространством имен общедоступного ресурса с помощью нескольких файлов заголовков. В разделе Техническое примечание 35. дополнительные сведения об использовании общих файлов ресурсов.

Инициализация библиотек DLL

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

Каждое клиентское приложение, которое нужно использовать библиотеку DLL должна вызывать эту процедуру инициализации, при использовании этого подхода. Можно также выбрать этот объект CDynLinkLibrary в DllMain сразу после вызова AfxInitExtensionModule.

Процедура инициализации следует создать объект CDynLinkLibrary в куче текущего приложения, проводной до XML-данных библиотеки DLL расширения. Это можно сделать следующим кодом:

extern "C" extern void WINAPI InitXxxDLL()
{
   new CDynLinkLibrary(extensionDLL);
}

Регулярная имя, InitXxxDLL в этом примере, может быть любым требуется. Для этого не требуется выполнять extern "C", но для этого список товаров экспортных удобнее для обслуживания.

Примечание

При использовании библиотеки расширения из обычных библиотек DLL, необходимо экспортировать эту функцию инициализации.Эта функция должна быть вызвана из обычных библиотек DLL до использования всех классов или ресурсов DLL расширения.

Экспортировать записи

Простым способом экспортирования классов использовать __declspec(dllimport) и __declspec(dllexport) в каждом классе и глобальной функции, который необходимо экспортировать. В этом случае будет значительно упрощает, но менее эффективно, чем именования каждую точку входа (описанный ниже), поскольку имеется меньше элемента управления, какие функции экспортируются и нельзя экспортировать функции по порядковому номеру. TESTDLL1 и TESTDLL2 используют этот метод, чтобы экспортировать их записи.

Более эффективный метод (и метод, используемый MFCxx.dll) экспортировать каждая запись вручную путем именования каждой записи в def-файле. Поскольку мы экспортируем селективные экспорты всего из библиотеки DLL (то есть не всего), нужно решить, интерфейсы, определенные в желаем экспортировать. Это затрудняет, поскольку необходимо указать кореженные имена компоновщику в форме записей в def-файле. Не экспортировать какие-либо классы C++, если это действительно не будет иметь символьную ссылку для надстройки.

Если попытка экспортировать классы C++ с файлом .DEF перед, может понадобиться разработать средства для создания этот список автоматически. Это можно сделать с помощью процесс двухэтапного ссылки. Свяжите библиотеки DLL один раз без экспортов и разрешить компоновщик для создания файла .MAP. Файл .MAP позволяет создавать список функций, которые должны быть экспортированы, поэтому с некоторые изменения, его можно использовать для создания пользовательских записей ЭКСПОРТА для файла .DEF. Список товаров для экспортных MFCxx.dll и OLE и библиотеки расширения базы данных, несколько тысяч в числа, созданный с текущим процессом (хотя и не полностью автоматическим и не требует определенных стороны в ходе каждый раз в это время).

CWinApp и CDynLinkLibrary

Библиотека DLL расширения MFC не имеет CWinApp- производного объекта его; вместо этого он должен работать с CWinApp- производным объектом клиентского приложения. Это означает, что клиентское приложение имеет цикла обработки сообщений, циклом бездействия и т д

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

Использование ресурсов в реализации библиотеки DLL

Как упоминалось выше, загрузка ресурсов по умолчанию просматривает список объектов CDynLinkLibrary и первые EXE или DLL с запрошенного ресурса. Все API MFC, так и полностью внутреннего кода используют AfxFindResourceHandle для обхода список ресурсов для поиска любой ресурс, независимо от того, где она может храниться.

При необходимости только загрузка ресурсов из определенного места следует использовать API AfxGetResourceHandle и AfxSetResourceHandle для сохранения старого дескриптора и задать новый дескриптор. Перед возвратом к клиентскому приложению убедитесь в том, что старый дескриптор ресурсов восстановлен. Пример TESTDLL2 использует этот подход для явной загрузки меню.

Проход по списку имеет тот недостаток, что он немного медленнее и требует управления уровнями идентификатора ресурса. Преимуществом является то, что клиентское приложение, связанное с несколькими библиотеками DLL расширения, может использовать любой предоставленный библиотекой DLL ресурс без указания дескриптора экземпляра библиотеки DLL. AfxFindResourceHandle представляет собой API, используемый для прохода по списку ресурсов в поиске заданного совпадения. В эту функцию передаются имя и тип ресурса, будет возвращен дескриптор ресурса, где он был найден в первый раз (или значение "NULL").

Написание приложение, которое использует версию библиотеки DLL

Прикладные требования

Приложение, которое использует общедоступную версию MFC, должно соответствовать несколько простых правил:

  • Он должен содержать объект CWinApp и выполнять стандартные правила для цикла обработки сообщений.

  • Он должен компилироваться с набором необходимых (см. ниже) флажков компилятора.

  • Он должен быть связан с библиотеками импорта MFCxx. Устанавливая компилятор (обязательный, заголовков MFC определяет во время ссылки, библиотека приложения должна компоноваться с.

  • Запуск исполняемого файла, MFCxx.dll должен располагаться по пути или в системном каталоге Windows.

Построение со средой разработки

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

В следующем шаге предполагается, что имеется правильной работе приложения MFC, связанное с NAFXCWD.LIB для (debug) и NAFXCW.LIB (для розницы) и необходимо преобразовать его для использования общей версии библиотеки MFC. При запуске среды Visual C++ существует внутреннего файл проекта.

  1. В меню Проекты выберите пункт Свойства. На странице Общие в области Значения по умолчанию для проекта задайте классы Microsoft Foundation в Использовать MFC в общей DLL (MFCxx (d) DLL).

Построение с помощью NMAKE

При использовании функции внешних файлов makefile Visual C или C++, используется NMAKE напрямую, то изменения в файлы makefile для поддержки компилятора и компоновщика

Необходимые флажки компилятора:

  • /D_AFXDLL /MD
    /D_AFXDLL

Стандартным заголовкам MFC должен указывать этот символ.

  • /MD
    Приложение должно использовать версию библиотеки DLL библиотеки времени выполнения C.

Все остальные флажки компилятора по умолчанию используется MFC (например, _DEBUG для отладки).

Правка список компоновщика библиотек. Измените NAFXCWD.LIB в MFCxxD.LIB и измените NAFXCW.LIB в MFCxx.LIB. Замените LIBC.LIB с MSVCRT.LIB. Как и любой другой библиотеки MFC важно MFCxxD.LIB для before все библиотеки C# выполнения.

При необходимости добавьте /D_AFXDLL и в рознице отладки и параметры компилятора ресурсов (единица, фактически компилировать ресурсы с /R). Это позволяет использовать окончательное исполняемого файла с наименьшим общий доступ к ресурсам, присутствующих в библиотеке DLL MFC.

Полное перестроение необходимо после того, как эти изменения будут внесены.

Построение образцов

Большинство примеров программ MFC можно построить из Visual C или C++ из общего NMAKE- совместимого ФАЙЛ MAKEFILE из командной строки.

Для преобразования любого из этих примеров для использования в файле можно загрузить файл .MAK в Visual C++ и настроить параметры проекта, как описано выше. При использовании построение NMAKE, можно задать «AFXDLL=1» в командной строке программы NMAKE, и строит образца в общие библиотеки MFC.

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

Примечания пакетов

Отладочная версия библиотеки DLL (MFCxx [U] .DLL) свободно распространяемый пакет. Отладочная версия библиотеки DLL не свободно распространяемый пакет и должна использоваться только в процессе разработки приложения.

Библиотека DLL отладки формируются с данными отладки. С помощью отладчика Visual C++ можно выполнения трассировки приложения, так и библиотеки DLL. Библиотека DLL выпуска (MFCxx [U] .DLL) не содержат данные отладки.

Если настраивается или перестроении библиотеки DLL необходимо вызвать их значения, отличные от «MFCxx» файл MFCDLL.MAK MFC SRC описаны параметры построения и содержит логику для переименования библиотеки DLL. Переименование файлов не требуется, поскольку эти библиотеки DLL потенциально используются несколькими приложениями MFC. Настройка пользовательскую версию библиотеки DLL MFC замените эти, установленые в системе может прервать другое приложение MFC с помощью общих библиотек DLL MFC.

Перестроить MFC DLL не рекомендуется.

MFCxx.dll реализуется как

В следующем разделе описано, как библиотека DLL MFC (MFCxx.dll и MFCxxD.DLL) реализуется. Общие сведения о здесь также не важны, если требуется задачи можно использовать библиотеку DLL MFC с приложением. Сведения, не требуется понимать, как для создания библиотеки DLL расширения MFC, но понимание это поведение может помочь написания собственного библиотеки DLL.

Общие сведения о реализации

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

Win32 выполняет большую часть работы

16 Разрядной версии MFC, требуется несколько специальных методов, включая данные для каждого приложения на сегмент стека, специальных сегментах созданных код сборки, 80x86 нескольких контекстах исключения в процессе и других методов. Win32 непосредственно поддерживает данных каждого процесса в библиотеку DLL, которая является требуемым большую часть времени. Большей части MFCxx.dll только NAFXCW.LIB упакованные в библиотеке DLL. При рассмотрении исходный код MFC, то предполагается очень немногий _AFXDLL #ifdef, поскольку имеется несколько особых случаев, которые необходимо выполнить. Особые случаи, существуют специально обрабатывать Win32 в Windows 3.1 (в противном случае в качестве Win32s). Win32s не поддерживает данные библиотеки DLL для каждого процесса, поэтому библиотека DLL MFC, необходимо использовать API Win32 (TLS) локальной памяти потока для получения процесс локальные данные.

Влияние на источниках библиотеки, дополнительных файлов

Влияние версии _AFXDLL для обычных источниках и заголовках библиотеки классов MFC относительно небольшой. Специальный файл версии (AFXV_DLL.H), так и дополнительного файла заголовка (AFXDLL_.H) включено заголовком main AFXWIN.H. Заголовок AFXDLL_.H содержит класс CDynLinkLibrary и другие сведения о реализации приложений, как _AFXDLL, так и библиотеки расширения MFC. Заголовок AFXDLLX.H предоставляется для построения библиотеки DLL расширения MFC (дополнительные сведения см. выше).

Обычные источников с библиотекой MFC в MFC SRC имеют некоторый дополнительный код в условный #ifdef _AFXDLL. Дополнительный файл источника (DLLINIT.CPP) содержит дополнительный код инициализации библиотеки DLL и другой клей для общей версией MFC.

Построение общедоступную версию MFC, дополнительные файлы предоставляются для. (См. ниже дополнительные сведения об использовании построение библиотеки DLL).

  • 2 Файла .DEF используются для экспортировать точки входа DLL MFC для отладки (MFCxxD.DEF) и освобождают версии (MFCxx.DEF) библиотеку DLL.

  • Rc-файл (MFCDLL.RC) содержит все стандартные ресурсы MFC и ресурс VERSIONINFO для библиотеки DLL.

  • Предоставляются для поддерживает файлы .CLW (MFCDLL.CLW) для просмотра классов MFC с помощью ClassWizard. Примечание. эта функция не определена в версии библиотек DLL MFC.

Управление памятью

Приложение, использующее MFCxx.dll использует общий распределитель, MSVCRTxx.DLL, общее DLL памяти C# выполнения. Приложение, все библиотеки DLL расширения, а сами хорошие в виде библиотеки DLL MFC использует этот распределитель общей памяти. С помощью общей библиотеки DLL для выделения памяти в библиотеке DLL MFC могут выделять память, будет освобождена или наоборот приложения. Поскольку приложения и DLL должны использовать один и тот же распределитель, не следует переопределить C++ глобальное operator new или operator delete. Те же правила, которые применяются к прочие процедур выделения памяти C времени выполнения (например, malloc, realloc, free и др.).

Порядковые номера и класса __declspec (dllexport) и имени библиотеки DLL

Мы не используется функция class __declspec(dllexport) компилятора C++. Вместо этого список экспортов включен с источниками библиотеки классов (MFCxx.DEF и MFCxxD.DEF). Только этот choice набор точек входа (функции и экспортировать данные). Другие символы, такие как функции или классы реализации MFC закрытой, не экспортируются все экспортам их порядковым номером без строковое имя в резиденте или нерезидентной имени таблицы.

С помощью class __declspec(dllexport) может быть жизнеспособным вариант для небольших при построении библиотеки DLL, но в случае большой библиотеки DLL с MFC, имеет ограничения по умолчанию экспортирования механизм эффективности и ресурсов.

Это означает, что все можно осуществить пакет большое количество функций в выпуске MFCxx.dll, только примерно 800 КБ без ущерба много времени выполнения или скорость загрузки. Не использовались MFCxx.dll будет 100K более большими этот метод. Это также дает возможность добавлять дополнительные точки входа в конце файла .DEF для разрешения простого элемента управления версиями без ущерба эффективность скорости и размера экспортироваться порядковым номером. Версии основного номера версий в библиотеке классов MFC изменяется имя библиотеки. То есть MFC30.DLL распространяемых библиотеки DLL, в версии 3.0 библиотеки классов MFC. Обновление данной библиотеки DLL, означает, постулативном в библиотеке DLL MFC 3.1, будет иметь имя MFC31.DLL вместо. Опять же, если изменить исходный код MFC для создания пользовательской версию библиотеки DLL MFC следует использовать другое имя (предпочтительно и без MFC «один» в имени).

См. также

Другие ресурсы

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

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