EXPORTS
Introduz uma seção de uma ou mais definições de exportação que especificam os nomes exportados ou ordenais de funções ou dados. Cada definição deve ficar em uma linha separada.
EXPORTS
definition
Comentários
A primeira definição pode estar na mesma linha que a palavra-chave EXPORTS
ou em uma linha subsequente. O arquivo .DEF pode conter uma ou mais instruções EXPORTS
.
A sintaxe para uma definição de exportação é:
entryname[=internal_name|other_module.exported_name] [@ordinal [NONAME] ] [ [PRIVATE] | [DATA] ]
entryname é o nome da função ou variável que você deseja exportar. Este campo é obrigatório. Se o nome exportado for diferente do nome na DLL, especifique o nome da exportação na DLL usando internal_name. Por exemplo, se o DLL exportar uma função func1
e você desejar que os chamadores a utilizem como func2
, especifique:
EXPORTS
func2=func1
Se o nome exportado for de algum outro módulo, especifique o nome da exportação na DLL usando other_module.exported_name. Por exemplo, se o DLL exportar uma função other_module.func1
e você desejar que os chamadores a utilizem como func2
, especifique:
EXPORTS
func2=other_module.func1
Se o nome exportado for de outro módulo exportado por ordinal, especifique o ordinal da exportação na DLL usando other_module.#ordinal. Por exemplo, se a DLL exportar uma função do outro módulo em que ela é ordinal 42 e você quiser que os chamadores a usem como func2
, especifique:
EXPORTS
func2=other_module.#42
Como o compilador do MSVC usa decoração de nome em funções do C++, é preciso usar o nome decorado como internal_name ou definir as funções exportadas usando extern "C"
no código-fonte. O compilador também decora funções do C que usam a convenção de chamada __stdcall com um prefixo de sublinhado (_) e um sufixo composto pelo sinal de arroba (@), seguido pelo número de bytes (em decimais) na lista de argumentos.
Para encontrar os nomes decorados produzidos pelo compilador, use a ferramenta DUMPBIN ou a opção /MAP do vinculador. Os nomes decorados são específicos do compilador. Se você exportar os nomes decorados no arquivo .DEF, executáveis vinculados ao DLL também devem ser construídos com a mesma versão do compilador. Isso garante que os nomes decorados no chamador correspondam aos nomes exportados no arquivo .DEF.
É possível usar @ordinal para especificar que um número, e não o nome da função, vai na tabela de exportação da DLL. Muitos DLLs do Windows exportam ordinais para dar suporte a código legado. Era comum usar ordinais em código do Windows de 16 bits, pois isso podia ajudar a minimizar o tamanho de um DLL. Não recomendamos exportar funções por ordinais, a menos que os clientes da DLL precisem disso para suporte legado. Como o arquivo .LIB conterá o mapeamento entre o ordinal e a função, é possível usar o nome da função como normalmente se faria em projetos que usam o DLL.
Usando a palavra-chave NONAME opcional, é possível exportar apenas por ordinal e reduzir o tamanho da tabela de exportação na DLL resultante. Porém, se você desejar usar GetProcAddress na DLL, deverá conhecer o ordinal, pois o nome não será válido.
A palavra-chave PRIVATE opcional impede que o entryname seja incluído na biblioteca de importação gerada por LINK. Não afeta a exportação na imagem também gerada por LINK.
A palavra-chave DATA opcional especifica que uma exportação é de dados, não código. Esse exemplo mostra como exportar uma variável de dados chamada exported_global
:
EXPORTS
exported_global DATA
Há quatro maneiras de exportar uma definição, listadas na ordem recomendada:
A palavra-chave __declspec(dllexport) no código-fonte
Uma instrução
EXPORTS
em um arquivo .DEFUma especificação /EXPORT em um comando da LINK
Uma diretiva comment no código fonte, da forma
#pragma comment(linker, "/export: definition ")
. O exemplo a seguir mostra uma diretiva de comentário #pragma antes de uma declaração de função, em quePlainFuncName
é o nome não decorado e_PlainFuncName@4
é o nome decorado da função:#pragma comment(linker, "/export:PlainFuncName=_PlainFuncName@4") BOOL CALLBACK PlainFuncName( Things * lpParams)
A diretiva #pragma será útil se você precisar exportar um nome de função não decorado e tiver exportações diferentes dependendo da configuração de build (por exemplo, em builds de 32 ou 64 bits).
Todos os quatro métodos podem ser usados no mesmo programa. Quando LINK compila um programa que contém exportações, ele também cria uma biblioteca de importação, a menos que um arquivo .EXP seja usado na construção.
Segue um exemplo de seção EXPORTS:
EXPORTS
DllCanUnloadNow @1 PRIVATE
DllWindowName = WindowName DATA
DllGetClassObject @4 NONAME PRIVATE
DllRegisterServer @7
DllUnregisterServer
Ao exportar uma variável de um DLL usando um arquivo .DEF, não é necessário especificar __declspec(dllexport)
na variável. Porém, em qualquer arquivo que use o DLL, ainda é preciso usar __declspec(dllimport)
na declaração de dados.