2010-08-26 10 views
9

cabecera de exportación DLLUna advertencia con DLL de 64 bits edificio

extern "C" 
void _declspec(dllexport) __stdcall foo(); 

archivo .def

EXPORTS 
foo   @1 

Cuando construyo el DLL de 64 bits por acumulación de configuración, que cumple con esta advertencia.

advertencia LNK4197: exportar 'foo' especificado varias veces; utilizando la primera especificación

Pero si construyo el dll mediante la configuración de compilación de 32 bits, la advertencia nunca ocurre.
¿Cuál es el problema? Cuál es la diferencia.

En encabezado DLL de interfaz, que suelen utilizar esta técnica,

#ifdef EXPORT_DLL 
#define BASICAPI _declspec(dllexport) 
#else 
#define BASICAPI _declspec(dllimport) 
#endif //_EXPORT_DLL 

Pero si también existe def archivo, siempre habrá satisfacer la advertencia cuando estamos construyendo DLL de 64 bits.
Entonces, ¿deberíamos escribir los códigos de esta manera?

#ifdef EXPORT_DLL 
#define BASICAPI 
#else 
#define BASICAPI _declspec(dllimport) 
#endif //_EXPORT_DLL 

Funciona bien. Pero no es familiar para mí.
Dame tu opinión.

Respuesta

11

En general, no es una buena práctica especificar exportaciones dos veces para la misma función. Si ya tiene __declspec(dllexport), entonces no necesita especificar la exportación en un archivo .def también. Por el contrario, si tiene la exportación enumerada en un archivo .def, entonces no hay necesidad de un __declspec(dllexport).

Creo que el motivo de la advertencia es que en las compilaciones x86, __declspec(dllexport) está exportando el nombre decorado con un guión bajo inicial, pero el compilador de 64 bits no decora los nombres con un guión bajo inicial, lo que da lugar al duplicado. Para verificar esto, podría ver la DLL de 32 bits en Dependency Walker y debería ver dos funciones exportadas, "foo" y "_foo".

+2

'64 compilador de bits no decora nombres 'No lo sabía. ¡Esa fue la razón! Gracias. – Benjamin

+0

Por cierto, ¿cómo puedo usar la fuente cursiva en el cuadro de comentarios? – Benjamin

+0

* decora * nombres, simplemente los decora de forma diferente al compilador de 32 bits (es decir, sin el subrayado inicial). Puede exportar una función dos veces con diferentes nombres (eso es lo que espero que esté sucediendo en sus compilaciones de 32 bits). La advertencia es porque en compilaciones de 64 bits, tanto el '__declspec' como el archivo .def darían como resultado el * mismo * nombre exportado, por lo que uno de ellos se considera redundante. –

5

__declspec(dllexport) y archivos .def son dos formas diferentes de exportar símbolos de un dll. No necesita ambos y debería omitirlos. El método __declspec es mucho más versátil para los programas de C++, ya que exporta nombres con C++ Mangling, lo que permite exportar funciones sobrecargadas, pero a la inversa hace que los nombres sean más difíciles de importar a través de GetProcAddress.

Además, el uso de una macro genérica como EXPORT_DLL es peligroso, ya que significa que no se puede construir un dll, que usa otro dll, sin que el otro intente exportar todos los símbolos de ambos dlls.

DevStudio crea automáticamente un símbolo en proyectos DLL: <PROJECT>_EXPORTS que es fácil y segura para crear una macro EXPORTACIÓN:

#ifdef EXPORT 
#undef EXPORT 
#endif 
#ifdef PROJECTNAMEHERE_EXPORTS 
#define EXPORT __declspec(dllexport) 
#else 
#define EXPORT __declspec(dllimport) 
#endif 

EXTERN_C EXPORT void __stdcall Function1(void); 
EXTERN_C EXPORT void __cdecl Function2(...); 
     EXPORT void Function3(void); 

Funciones 1 & 2 se pueden conseguir con GetProcAddress como [email protected] y Function2 respectivamente. La función 3 se exportará a través de un nombre destrozado específico del compilador que se verá algo así como: @[email protected]@[email protected]. Este nombre es diferente para cada sobrecarga de la función, que es cómo permite que funcione la sobrecarga.

Es importante saber el nombre de mangling __declspec archivos como .DEF no les importa y que acaba de exportar Function1, Function2 y Function3.

+1

Su primer párrafo es más o menos lo que estaba tratando de decir con * mi * primer párrafo, pero lo dijo mucho mejor que yo, +1 :) –

+0

Agradable respuesta y comentario. +1 :) – Benjamin

+0

Yo, por el contrario, no sabía nada de la cosa de 64 bits. –

Cuestiones relacionadas