EXPORTS
Presenta una sección de una o varias definiciones de exportación que especifican los nombres o los ordinales exportados de las funciones o los datos. Cada definición debe estar en una línea independiente.
EXPORTS
definition
Comentarios
La primera definición puede estar en la misma línea que la palabra clave EXPORTS
o en una de las siguientes. El archivo .DEF puede contener una o varias instrucciones EXPORTS
.
La sintaxis de una definición de exportación es:
entryname[=internal_name|other_module.exported_name] [@ordinal [NONAME] ] [ [PRIVATE] | [DATA] ]
entryname es el nombre de la función o la variable que quiere exportar. Esto es obligatorio. Si el nombre que exporta es distinto del nombre que aparece en la DLL, especifique el nombre de la exportación incluido en la DLL con internal_name. Por ejemplo, si la DLL exporta una función func1
y quiere que los autores de llamadas la usen como func2
, tendrá que especificar:
EXPORTS
func2=func1
Si el nombre que exporta es de otro módulo, especifique el nombre de la exportación en la DLL mediante other_module.exported_name. Por ejemplo, si la DLL exporta una función other_module.func1
y quiere que los autores de llamadas la usen como func2
, tendrá que especificar:
EXPORTS
func2=other_module.func1
Si el nombre que exporta es de otro módulo que exporta por ordinal, especifique el ordinal de la exportación en la DLL mediante other_module.#ordinal. Por ejemplo, si la DLL exporta una función de otro módulo en el que es ordinal 42 y quiere que los autores de llamadas la usen como func2
, debe especificar:
EXPORTS
func2=other_module.#42
Como el compilador de MSVC usa los nombres representativos para las funciones de C++, debe usar el nombre representativo internal_name o definir las funciones exportadas con extern "C"
en el código fuente. El compilador también usa funciones representativas de C que emplean la convención de llamada __stdcall con un prefijo de subrayado (_) y un sufijo formado por una arroba (@) seguida del número de bytes (en decimal) en la lista de argumentos.
Para buscar los nombres representativos producidos por el compilador, use la herramienta DUMPBIN o la opción del enlazador /MAP. Los nombres representativos son específicos de cada compilador. Si exporta los nombres representativos en el archivo .DEF, los ejecutables que vinculen a la DLL se deberán compilar con la misma versión del compilador. Así, nos aseguramos de que los nombres representativos del autor de la llamada coincidan con los nombres exportados del archivo .DEF.
Puede usar @ ordinal para especificar que un número, y no el nombre de la función, vaya a la tabla de exportación de la DLL. Muchas DLL de Windows exportan ordinales para admitir código heredado. En el código de Windows de 16 bits, era habitual usar ordinales, porque con ellos puede ser más fácil minimizar el tamaño de las DLL. No recomendamos exportar las funciones por ordinales, salvo que los clientes de su DLL lo necesiten para admitir el código heredado. Dado que el archivo .LIB contendrá la asignación entre el ordinal y la función, puede usar el nombre de la función como lo haría normalmente en los proyectos que usan la DLL.
Con la palabra clave opcional NONAME, puede exportar solo por ordinal y reducir el tamaño de la tabla de exportación en la DLL resultante. Sin embargo, si quiere usar GetProcAddress en la DLL, debe conocer el ordinal, ya que el nombre no será válido.
La palabra clave opcional PRIVATE impide que entryname se incluya en la biblioteca de importación generada por LINK. No afecta a la exportación de la imagen que también genera LINK.
La palabra clave opcional DATA especifica que una exportación es de datos y no de código. Este ejemplo le muestra cómo podría exportar una variable de datos llamada exported_global
:
EXPORTS
exported_global DATA
Puede exportar una definición de estas cuatro formas, por orden de más a menos recomendadas:
La palabra clave __declspec(dllexport) en el código fuente
Una instrucción
EXPORTS
en un archivo .DEFUna especificación /EXPORT en un comando de LINK
Una directiva comment en el código fuente, con la forma
#pragma comment(linker, "/export: definition ")
En el ejemplo siguiente se muestra una directiva de comentario #pragma antes de una declaración de función, dondePlainFuncName
es el nombre no representativo y_PlainFuncName@4
es el nombre representativo de la función:#pragma comment(linker, "/export:PlainFuncName=_PlainFuncName@4") BOOL CALLBACK PlainFuncName( Things * lpParams)
La directiva #pragma es útil si necesita exportar un nombre de función no representativo y tener diferentes exportaciones dependiendo de la configuración de compilación (por ejemplo, en compilaciones de 32 o 64 bits).
Se pueden utilizar los cuatro métodos en el mismo programa. Cuando LINK compila un programa que contiene exportaciones, crea también una biblioteca de importación, excepto si se usa un archivo .EXP en la compilación.
Este es un ejemplo de una sección EXPORTS:
EXPORTS
DllCanUnloadNow @1 PRIVATE
DllWindowName = WindowName DATA
DllGetClassObject @4 NONAME PRIVATE
DllRegisterServer @7
DllUnregisterServer
Al exportar una variable de una DLL con un archivo .DEF, no es necesario que especifique __declspec(dllexport)
en la variable. Sin embargo, en todos los archivos que utilicen la DLL, deberá usar __declspec(dllimport)
en la declaración de datos.