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

Существует четыре способа экспорта определения; здесь они перечислены в порядке предпочтительности:

  1. Ключевое слово __declspec(dllexport) в исходном коде

  2. оператор EXPORTS в файле DEF;

  3. Спецификация /EXPORT в команде LINK

  4. Директива комментария в исходном коде формы #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) для объявления данных.

См. также

Правила для операторов определения модуля