EXPORTS
Introduce una sezione di una o più definizioni di esportazione che specificano i nomi o gli ordinali esportati di funzioni o dati. Ogni definizione deve essere riportata in una riga separata.
EXPORTS
definition
Osservazioni:
La prima definizione può trovarsi nella stessa riga della EXPORTS
parola chiave o in una riga successiva. Il file con estensione DEF può contenere una o più istruzioni EXPORTS
.
La sintassi per una definizione di esportazione è:
entryname[=internal_name|other_module.exported_name] [@ordinal [NONAME] ] [ [PRIVATE] | [DATA] ]
entryname è il nome della funzione o della variabile da esportare. Questa convalida è obbligatoria. Se il nome esportato è diverso dal nome nella DLL, specificare il nome dell'esportazione nella DLL usando internal_name. Se ad esempio la DLL esporta una funzione func1
e si vuole che i chiamanti la usino come func2
, specificare:
EXPORTS
func2=func1
Se il nome esportato proviene da un altro modulo, specificare il nome dell'esportazione nella DLL usando other_module.exported_name. Se ad esempio la DLL esporta una funzione other_module.func1
e si vuole che i chiamanti la usino come func2
, specificare:
EXPORTS
func2=other_module.func1
Se il nome esportato proviene da un altro modulo che esporta per ordinale, specificare l'ordinale dell'esportazione nella DLL usando other_module.#ordinale. Ad esempio, se la DLL esporta una funzione dall'altro modulo in cui è ordinale 42 e si vuole che i chiamanti lo usino come func2
, specificare:
EXPORTS
func2=other_module.#42
Poiché il compilatore MSVC usa la decorazione dei nomi per le funzioni C++, è necessario usare il nome decorato internal_name o definire le funzioni esportate usando extern "C"
nel codice sorgente. Il compilatore decora anche le funzioni C che usano la convenzione di chiamata __stdcall con un prefisso di sottolineatura (_) e un suffisso composto dal segno di corrispondenza (@) seguito dal numero di byte (in decimale) nell'elenco di argomenti.
Per trovare i nomi decorati generati dal compilatore, usare lo strumento DUMPBIN o l'opzione linker /MAP . I nomi decorati sono specifici del compilatore. Se si esportano i nomi decorati nel file .DEF, gli eseguibili che si collegano alla DLL devono essere anch'essi compilati usando la stessa versione del compilatore. Questo garantisce che i nomi decorati nel chiamante corrispondano ai nomi esportati nel file .DEF.
È possibile usare @ordinal per specificare che un numero e non il nome della funzione passa alla tabella di esportazione della DLL. Molte DLL Windows esportano ordinali per supportare il codice legacy. In precedenza, era pratica comune usare ordinali nel codice Windows a 16 bit, perché ciò può aiutare a ridurre le dimensioni di una DLL. Non è consigliabile esportare le funzioni in base all'ordinale, a meno che i client della DLL non ne richiedano il supporto legacy. Dato che il file .LIB file conterrà il mapping tra l'ordinale e la funzione, è possibile usare il nome della funzione come si farebbe normalmente nei progetti che usano la DLL.
Usando la parola chiave NONAME facoltativa, è possibile esportare solo per ordinale e ridurre le dimensioni della tabella di esportazione nella DLL risultante. Tuttavia, se si vuole usare GetProcAddress nella DLL, è necessario conoscere l'ordinale perché il nome non sarà valido.
La parola chiave facoltativa PRIVATE impedisce l'inserimento di entryname nella libreria di importazione generata da LINK. Questa non ha alcun effetto sull'esportazione nell'immagine, anch'essa generata da LINK.
La parola chiave facoltativa DATA specifica che un'esportazione è dati, non codice. L'esempio seguente illustra come esportare una variabile dati denominata exported_global
:
EXPORTS
exported_global DATA
Vi sono quattro metodi per esportare una definizione, elencati di seguito in ordine di preferenza.
Parola chiave __declspec(dllexport) nel codice sorgente
Un'istruzione
EXPORTS
in un file .DEFSpecifica /EXPORT in un comando LINK
Direttiva commento nel codice sorgente, del formato
#pragma comment(linker, "/export: definition ")
. Nell'esempio seguente viene illustrata una direttiva di commento #pragma prima di una dichiarazione di funzione, dovePlainFuncName
è il nome non dichiarato e_PlainFuncName@4
è il nome decorato della funzione:#pragma comment(linker, "/export:PlainFuncName=_PlainFuncName@4") BOOL CALLBACK PlainFuncName( Things * lpParams)
La direttiva #pragma è utile se è necessario esportare un nome di funzione nondecorato e avere esportazioni diverse a seconda della configurazione di compilazione, ad esempio nelle compilazioni a 32 bit o a 64 bit.
Tutti e quattro i metodi possono essere usati nello stesso programma. Quando LINK compila un programma che contiene esportazioni, crea anche una libreria di importazione, a meno che non venga usato un file .EXP nella compilazione.
Di seguito è riportato un esempio di sezione EXPORTS:
EXPORTS
DllCanUnloadNow @1 PRIVATE
DllWindowName = WindowName DATA
DllGetClassObject @4 NONAME PRIVATE
DllRegisterServer @7
DllUnregisterServer
Quando si esporta una variabile da una DLL usando un file .DEF, non è necessario specificare __declspec(dllexport)
nella variabile. In qualsiasi file che usa la DLL, tuttavia, è comunque necessario usare __declspec(dllimport)
nella dichiarazione dei dati.