2010-02-17 12 views
8

Entorno: Visual Studio 9, C++ sin extensiones administradas.DLL y clase de plantilla totalmente especializada

Tengo una biblioteca de terceros que exporta una clase de plantilla totalmente especializada MyClass<42> definida en MyClass.h. Se compila en un cargador auxiliar .lib y un archivo .dll. El archivo .lib contiene código compilado para esta especialización y los símbolos necesarios. El MyClass.h se ve así:

template<UInt D> 
class MyClass { 
public: 
    MyClass() {...}; 
    virtual ~MyClass() {}; 
} 

Ahora me gustaría utilizar esta biblioteca. Si incluyo MyClass.h en un Client.cpp y luego lo compilo, obtendré una segunda copia de estos símbolos en el archivo Client.obj. Puedo deshacerme de estos símbolos definiendo a todos los miembros de esa especialización como "externos". Mi Client.cpp se ve así:

#include <ThirdParty/MyClass.h> 

extern template class MyClass<42>; 
extern template MyClass<42>::MyClass<42>(); 
extern template MyClass<42>::~MyClass<42>(); 

void MyFunction(MyClass<42>& obj) {...} 

El problema es que no puedo deshacerse del destructor virtual de esta manera. Para el destructor virtual obtengo un error LNK2005 casi estándar:

ThirdPartyd.lib(ThirdPartyd.dll) : error LNK2005: 
    "public: virtual __thiscall MyClass<42>::~MyClass<42>(void)" 
    ([email protected][email protected]@@[email protected]) already defined in Client.obj 

¿Qué debo hacer?

Respuesta

4

Parece que para los métodos virtuales es necesario definirlos como tanto extern y __declspec(dllimport) al mismo tiempo:

extern template __declspec(dllimport) MyClass<42>::~MyClass<42>(); 

Esto hizo que mi enlazador suficientemente feliz para enlazar el código correctamente.

Estaría muy contento si algún experto describiera por qué es así, o al menos apuntando a algún artículo que explica este caso.

1

Creo que Visual Studio usa la especialización de plantillas en dlls para algunas construcciones stl. string viene a la mente,

Tenía una mirada rápida en el archivo de cabecera, y parece que se trata de utilizar

__declspec(dllimport) 

en la declaración de un montón de especialidades. Sin embargo, no parece que lo haga para toda la clase.

De this discussion parece que es posible declarar toda la clase como exportada, pero no dice cómo.

Perdón por la respuesta no tan completa, pero con suerte, esto puede ayudarlo a explorar otros lugares.

+0

+1 Me alegro de que incluso hayas dado una propina tan pequeña. – liori

Cuestiones relacionadas