Экспортирование и импортирование с использованием AFX_EXT_CLASS
Библиотеки DLL расширения MFC используют макрос AFX_EXT_CLASS для экспорта классов; исполняемые файлы, которые связываются с библиотекой DLL расширения MFC, используют макрос для импорта классов. При использовании макроса AFX_EXT_CLASS те же файлы заголовков, которые используются для сборки библиотеки DLL расширения MFC, можно использовать с исполняемыми файлами, которые связываются с библиотекой 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
, это означает, что целевой исполняемый файл является библиотекой DLL расширения MFC.
Поскольку при экспорте из библиотеки DLL расширения MFC AFX_EXT_CLASS
определяется как __declspec(dllexport)
, можно экспортировать целые классы без добавления внутренних имен для всех символов этого класса в DEF-файле.
Хотя можно не создавать DEF-файл и все внутренние имена класса с помощью этого метода, создание DEF-файла является более эффективным способом, так как имена можно экспортировать по порядковому номеру. Чтобы использовать метод экспорта с применением DEF-файла, поместите следующий код в начало и в конец файла заголовка:
#undef AFX_DATA
#define AFX_DATA AFX_EXT_DATA
// <body of your header file>
#undef AFX_DATA
#define AFX_DATA
Внимание
Будьте внимательны при экспорте встроенных функций, поскольку они могут создать вероятность конфликтов версий. Встроенная функция расширяется в код приложения; поэтому при последующей перезаписи функции она не обновляется, пока не будет перекомпилировано само приложение. Как правило, функции 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
определяется следующим образом при сборке библиотеки DLL расширения MFC.
#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
.
Примечание.
При экспорте всего класса вместо отдельных элементов класса статические элементы данных экспортируются автоматически.