EXPORTS
Начинает раздел, состоящий из одного или нескольких определений экспорта, в которых указываются имена или порядковые номера экспортируемых функций или данных. Каждое определение должно находиться в отдельной строке.
EXPORTS
definition
Замечания
Первое определение может находиться в той же строке, что EXPORTS
и ключевое слово или в следующей строке. В файле DEF могут содержаться один или несколько операторов EXPORTS
.
Синтаксис определения экспорта:
entryname[=internal_name other_module.exported|_name] [@порядковый номер [NONAME] [ [PRIVATE] | [DATA] ]
имя записи — это имя функции или переменной, которую требуется экспортировать. Это обязательное поле. Если экспортируемая имя отличается от имени в библиотеке DLL, укажите имя экспорта в библиотеке DLL с помощью internal_name. Например, если библиотека DLL экспортирует функцию func1
и вы хотите, чтобы она вызывалась как функция func2
, укажите следующее.
EXPORTS
func2=func1
Если экспортируемая имя выполняется из другого модуля, укажите имя экспорта в библиотеке DLL с помощью other_module.exported_name. Например, если библиотека DLL экспортирует функцию other_module.func1
и вы хотите, чтобы она вызывалась как функция func2
, укажите следующее.
EXPORTS
func2=other_module.func1
Если имя, экспортируемом из другого модуля, экспортируемого порядком, укажите порядковый номер экспорта в библиотеке DLL с помощью other_module.#порядковый номер. Например, если библиотека DLL экспортирует функцию из другого модуля, где она имеет порядковый номер 42, и вы хотите, чтобы вызывающие пользователи использовали ее как func2
, следует указать:
EXPORTS
func2=other_module.#42
Так как компилятор MSVC использует декорирование имен для функций C++, необходимо либо использовать декорированное имя internal_name , либо определить экспортированные функции с помощью extern "C"
исходного кода. Компилятор также декорирует функции C, использующие соглашение о вызове __stdcall с префиксом подчеркивания (_) и суффиксом, состоящим из знака (@), за которым следует число байтов (десятичное значение) в списке аргументов.
Чтобы найти украшенные имена, созданные компилятором, используйте средство DUMPBIN или параметр компоновщика /MAP . Декорированные имена зависят от компилятора. Если вы экспортируете декорированные имена в файле DEF, сборка исполняемых файлов, связанных с библиотекой DLL, должна осуществляться с помощью той же версии компилятора. Таким образом обеспечивается совпадение декорированных имен в вызывающем объекте с экспортированными именами в файле DEF.
Можно использовать номер @ordinal , чтобы указать, что число, а не имя функции, переходит в таблицу экспорта библиотеки DLL. Многие библиотеки DLL Windows экспортируют порядковые номера для поддержки устаревшего кода. В 16-разрядном коде Windows часто использовались порядковые номера, так как это позволяло уменьшить размер DLL. Мы не рекомендуем экспортировать функции по порядковой версии, если клиенты библиотеки DLL не нуждаются в его поддержке прежних версий. Файл LIB будет содержать сопоставление между порядковым номером и функцией, что позволит использовать имя функции, как обычно в проектах, использующих DLL.
Используя необязательное ключевое слово NONAME , можно экспортировать только порядковый номер и уменьшить размер таблицы экспорта в результирующем библиотеке DLL. Однако если вы хотите использовать GetProcAddress в библиотеке DLL, необходимо знать порядковый номер, так как имя не будет допустимым.
Необязательное ключевое слово PRIVATE предотвращает включение имени записи в библиотеку импорта, созданную link. Оно не влияет на экспорт в образ, также созданный с помощью LINK.
Необязательное ключевое слово DATA указывает, что экспорт — это данные, а не код. Например, переменную с именем exported_global
, содержащую данные, можно экспортировать так.
EXPORTS
exported_global DATA
Существует четыре способа экспорта определения; здесь они перечислены в порядке предпочтительности:
Ключевое слово __declspec(dllexport) в исходном коде
оператор
EXPORTS
в файле DEF;Спецификация /EXPORT в команде LINK
Директива комментария в исходном коде формы
#pragma comment(linker, "/export: definition ")
. В следующем примере показана директива комментария #pragma перед объявлением функции, гдеPlainFuncName
является неоцененным именем и_PlainFuncName@4
является украшенным именем функции:#pragma comment(linker, "/export:PlainFuncName=_PlainFuncName@4") BOOL CALLBACK PlainFuncName( Things * lpParams)
Директива #pragma полезна, если необходимо экспортировать неоценённое имя функции и иметь разные экспорты в зависимости от конфигурации сборки (например, в 32-разрядных или 64-разрядных сборках).
Все эти методы можно использовать в одной программе. Когда программа LINK создает программу, содержащую экспорты, она также создает библиотеку импорта (если только при построении не используется файл EXP).
Ниже приведен пример раздела EXPORTS.
EXPORTS
DllCanUnloadNow @1 PRIVATE
DllWindowName = WindowName DATA
DllGetClassObject @4 NONAME PRIVATE
DllRegisterServer @7
DllUnregisterServer
Если экспортируется переменная из библиотеки DLL с помощью файла DEF, вам не надо указывать __declspec(dllexport)
для переменной. Однако в любом файле, использующем библиотеку DLL, вы должны использовать __declspec(dllimport)
для объявления данных.