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


Экспортирование и импортирование с использованием AFX_EXT_CLASS

Обновлен: Ноябрь 2007

Библиотеки расширений используют макросы AFX_EXT_CLASS для экспортирования классов. Исполняемые файлы, связанные с библиотекой расширения, используют данный макрос для импортирования классов. Кроме макроса AFX_EXT_CLASS файл заголовка, который используется для построения библиотеки расширения, также может применяться вместе с исполняемыми файлами, связанными с библиотеками DLL.

В файле заголовка для библиотеки DLL ключевое слово AFX_EXT_CLASS добавляется в объявление класса следующим образом:

class AFX_EXT_CLASS CMyClass : public CDocument
{
// <body of class>
};

Библиотека MFC определяет макрос в качестве __declspec(dllexport), когда определяются символы предпроцессора _AFXDLL и _AFXEXT. Макрос определяется в качестве __declspec(dllimport), когда определяется _AFXDLL и не определяется _AFXEXT. После завершения процесса определения символ предпроцессора _AFXDLL показывает, что общая версия MFC используется исполняемым целевым файлом (библиотекой DLL или приложением). Определение и символа _AFXDLL, и _AFXEXT указывает на то, что исполняемый целевой файл является библиотекой расширения.

Во время экспортирования из библиотеки расширения AFX_EXT_CLASS определяется в качестве __declspec(dllexport). Это позволяет экспортировать все классы, не заменяя в DEF-файле декорированные имена символов класса. В приведенном примере этот метод используется библиотекой MFC DLLHUSK.

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

#undef AFX_DATA
#define AFX_DATA AFX_EXT_DATA
// <body of your header file>
#undef AFX_DATA
#define AFX_DATA
9xyb5w93.alert_caution(ru-ru,VS.90).gifВнимание!

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

Экспортирование отдельных членов в класс

Время от времени может возникать необходимость экспортирования отдельных членов в класс. Например, при экспортировании класса, производного от CDialog, возможно, потребуется экспортировать только конструктора и вызов DoModal. Для выполнения экспортирования отдельных членов можно также использовать 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, объявляет о статическом объекте внутри класса. Чтобы правильно экспортировать класс и получить доступ к данным исполняемого клиентского файла во время выполнения, необходимо экспортировать статический объект. Поскольку статический объект объявляется вместе с модификатором 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.

9xyb5w93.alert_note(ru-ru,VS.90).gifПримечание.

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

Выполняемые задачи

Дополнительные сведения

См. также

Основные понятия

Экспорт из библиотеки DLL