2010-02-18 13 views
18

¿Cuál es la diferencia/relación entre "extern" y "__declspec (dllimport")? Descubrí que a veces es necesario usar ambos, a veces uno es suficiente.Windows y C++: extern & __declspec (dllimport)

Estoy en lo cierto que:

  1. "externo" es para las bibliotecas enlazadas estáticamente,
  2. "__declspec (dllimport)" es para DLL (bibliotecas de enlace dinámico),
  3. ambos hacen realidad la misma trabajo para su respectivo tipo de enlace,
  4. necesita usar ambos cuando usa bibliotecas de importación (archivos .lib pequeños que ayudan a enlazar con dll)?

Respuesta

30

extern significa que la entidad tiene un enlace externo, es decir, es visible fuera de su unidad de traducción (archivo C o CPP). La implicación de esto es que se colocará un símbolo correspondiente en el archivo objeto, y por lo tanto también será visible si este archivo objeto se hace parte de una biblioteca estática. Sin embargo, extern no implica que el símbolo también será visible una vez que el archivo objeto se hace parte de una DLL.

__declspec(dllexport) significa que el símbolo se debe exportar desde una DLL (si de hecho forma parte de una DLL). Se usa al compilar el código que va a la DLL.

__declspec(dllimport) significa que el símbolo se importará de una DLL. Se usa al compilar el código que usa el DLL.

Debido a que el mismo fichero de cabecera se utiliza normalmente tanto al compilar el archivo DLL en sí, así como el código de cliente que va a utilizar el archivo DLL, se acostumbra a definir una macro que se resuelve en __declspec(dllexport) al compilar el archivo DLL y __declspec(dllimport) al compilar su cliente, así:

#if COMPILING_THE_DLL 
    #define DLLEXTERN __declspec(dllexport) 
#else 
    #define DLLEXTERN __declspec(dllimport) 
#endif 

para responder a sus preguntas específicas:

  1. Sí, extern por sí solo es suficiente para bibliotecas estáticas.
  2. Sí - y la declaración también necesita un extern (see explanation here).
  3. No del todo - ver arriba.
  4. No necesita estrictamente el extern con un __declspec(dllimport) (consulte la explicación vinculada a arriba), pero como normalmente usará el mismo archivo de encabezado, ya tendrá el extern allí porque es necesario al compilar el DLL.
+0

Anuncio 4 .: ¿Qué sucede con los métodos virtuales en línea? AFAIK necesitan 'extern'; esto es en realidad lo que encontré en http://stackoverflow.com/questions/2284648/dll-and-fully-specialized-template-class – liori

+1

Para las clases, el enfoque más manejable (y habitual) es declarar toda la clase '__declspec (dllexport) '. La exportación de miembros individuales de la clase es más complicada ... ver, por ejemplo, http://msdn.microsoft.com/en-us/library/81h27t8c%28VS.80%29.aspx. –

Cuestiones relacionadas