2008-08-25 13 views
8

Estoy escribiendo un C/C++ DLL y quieren exportar ciertas funciones que he hecho antes de utilizar un archivo .def como estofunciones sobrecargadas en C++ DLL archivo DEF

LIBRARY "MyLib" 
EXPORTS 
    Foo 
    Bar 

con el código definido como esto, por ejemplo:

int Foo(int a); 
void Bar(int foo); 

Sin embargo, lo que si quiero declarar un método sobrecargado de Foo() como:

int Foo(int a, int b); 

como el d El archivo ef solo tiene el nombre de la función y no el prototipo completo. No puedo ver cómo manejaría las funciones sobrecargadas. ¿Utiliza la única entrada y luego especifica qué versión sobrecargada desea al pasar el puntero de la función de prototipo adecuado a LoadLibrary()?

Editar: Para ser claros, esto es en Windows utilizando Visual Studio 2005

Editar: Marcado el método no-def (__declspec) como la respuesta ... Sé que esto en realidad no resuelve el problema utilizando Definir archivos como yo quería, pero parece que no hay una solución (oficial) que use archivos def. Sin embargo, dejaremos la pregunta abierta, en caso de que alguien sepa algo, no tenemos funciones sobrecargadas ni archivos def.

Respuesta

9

En el propio código, marque las funciones que desee exportar el uso de __declspec (dllexport). Por ejemplo:

#define DllExport __declspec(dllexport) 

int DllExport Foo(int a) { 
    // implementation 
} 
int DllExport Foo(int a, int b) { 
    // implementation 
} 

Si hace esto, no es necesario enumerar las funciones en el archivo .def.

Alternativamente, es posible que pueda utilizar un valor de parámetro predeterminado, como:

int Foo(int a, int b = -1) 

Esto supone que existe un valor de b que se puede utilizar para indicar que no se ha utilizado. Si -1 es un valor legal para b, o si no hay o no debe haber un valor predeterminado, esto no funcionará.

Editar (Adam Haile): Se corrigió el uso de __declspec ya que __dllspec no era correcto, así que pude marcar esto como la respuesta oficial ... estaba lo suficientemente cerca.

Editar (Graeme): Oops - gracias por corregir mi error tipográfico!

+0

¿Qué sucede si utilizamos GetProcAddress() con una DLL dinámica? – null

+2

Luego necesita usar los nombres truncados, o renombrar una de las funciones y hacer que ambas sean 'extern" C "', suponiendo que ninguna de ellas toma o devuelve objetos C++. –

11

sobrecarga de funciones es una función de C++ que se basa en el nombre mangling (los nombres de función crípticos en los mensajes de error enlazador).

Al escribir los nombres alterados en el archivo de definición, puedo conseguir mi proyecto de prueba para enlazar y ejecutar:

LIBRARY "TestDLL" 
EXPORTS 
    [email protected]@[email protected] 
    [email protected]@[email protected] 

parece funcionar para

void Foo(int x); 
void Foo(int x, int y); 

Así copiar las ++ nombres de función C de el mensaje de error y escríbalos en tu archivo def. Sin embargo, la verdadera pregunta es: ¿Por qué quieres usar un archivo def y no ir con __declspec (dllexport)?

Los nombres alterados son no portátil, he probado con VC++ 2008.

+0

Enfoque interesante. ¿Por no portátil te refieres a diferentes versiones de Visual Studio? ¿Qué sugeriría que cambien sus esquemas de mangle entre versiones tal vez? – jxramos

+0

@jxramos No estoy seguro de si realmente pueden cambiar el esquema de cambio de nombre. Pero dudo que esto funcione de la misma manera cuando cambie a otro compilador, a menos que el compilador intente emular el comportamiento de VC. – Timbo

+0

Esto seguramente es solo algo de VC++ ya que no creo que otros compiladores usen archivos def. También si recuerdo lo que alguien me dijo una vez es que Microsoft tiene esta idea de interfaz dll donde los elementos seleccionados por el usuario se exponen públicamente, a través del archivo def o __declspec mientras que en Unix con sus archivos * .so se expone todo con una API pública. No tienen una distinción entre la API pública lógica y la API pública de la biblioteca. – jxramos

2

No existe una forma de agnóstico de idioma o versión para exportar una función sobrecargada ya que la convención de manipulación puede cambiar con cada versión del compilador.

Esta es una razón por la cual la mayoría de las funciones de WinXX tienen nombres divertidos como * Ex o * 2.

+0

¡fondo interesante con el comentario de WinXX! – jxramos

3

No hay forma oficial de hacer lo que desea, porque la interfaz dll es una API.

El compilador utiliza nombres mutilados como una solución, por lo que debe utilizar el cambio de nombre cuando no desee cambiar demasiado en su código.

8

Tuve un problema similar, así que quería publicarlo también.

  1. Por lo general, el uso de

    extern "C" __declspec(dllexport) void Foo(); 
    

    exportar un nombre de función está muy bien. Será generalmente exportar el nombre sin protección sin la necesidad de un archivo .def. Sin embargo, existen algunas excepciones , como __stdcall functions y nombres de funciones sobrecargados.

  2. Si se declara una función para utilizar la convención __stdcall (como se hace para muchas funciones API) y luego

    extern "C" __declspec(dllexport) void __stdcall Foo(); 
    

    exportará un nombre revuelto como _foo @ 4. En este caso, es posible que necesite asignar explícitamente el nombre exportado a un nombre interno destruido.

A. Cómo exportar un nombre no protegido. En un archivo .def añadir

---- 
EXPORTS 
    ; Explicit exports can go here 

    Foo 
----- 

Esto tratar de encontrar una "mejor partido" para una función interna de Foo y exportarlo. En el caso anterior donde sólo hay uno foo esto creará el mapeo

Foo = _foo @ 4

como se puede ver a través de dumpbin/EXPORTACIONES

si ha sobrecargado el nombre de la función, entonces Es posible que necesite indicar explícitamente qué función desea en el archivo .def especificando un nombre destruido utilizando la sintaxis entryname [= internalname]. p.ej.

---- 
EXPORTS 
    ; Explicit exports can go here 

    [email protected] 
----- 

B. Una alternativa a los archivos .def es que puede exportar nombres "en su lugar" usando un #pragma.

#pragma comment(linker, "/export:[email protected]") 

C. Una tercera alternativa es declarar sólo una versión de Foo como extern "C" a ser exportados unmangled. Ver here para más detalles.

2

Systax para las exportaciones definición es:

entryname[=internalname] [@ordinal [NONAME]] [PRIVATE] [DATA] 

nombreEntrada es la función o el nombre de la variable que desea exportar. Esto es requerido. Si el nombre que exporta es diferente del nombre en la DLL, especifique el nombre de la exportación en la DLL con el nombre interno.

Por ejemplo, si el archivo DLL exporta una función, func1() y desea que sea utilizado como func2(), se especificaría:

EXPORTS 
func2=func1 

Sólo hay que ver los nombres alterados (usando Dependency Walker) y especifica el nombre de tu propia función.

Fuente: http://msdn.microsoft.com/en-us/library/hyx1zcd3(v=vs.71).aspx

Editar: Esto funciona para archivos DLL dinámicas, en las que debemos utilizar GetProcAddress() en busca de una forma explícita las funciones de la DLL.

Cuestiones relacionadas