DLL и полностью специализированный шаблонный класс - PullRequest
8 голосов
/ 18 февраля 2010

Среда: Visual Studio 9, C ++ без управляемых расширений.

У меня есть сторонняя библиотека, которая экспортирует полностью специализированный шаблонный класс MyClass<42>, определенный в MyClass.h.Он компилируется в загрузчик вспомогательных файлов .lib и .dll.Файл .lib содержит скомпилированный код для этой специализации и необходимые символы.MyClass.h выглядит следующим образом:

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

Теперь я хотел бы использовать эту библиотеку.Если я включу MyClass.h в Client.cpp, а затем скомпилирую его, я получу вторую копию этих символов в файле Client.obj.Я могу избавиться от этих символов, определив всех членов этой специализации как "extern".Мой Client.cpp выглядит так:

#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) {...}

Проблема в том, что я не могу избавиться от виртуального деструктора таким образом.Для виртуального деструктора я получаю почти стандартную ошибку LNK2005:

ThirdPartyd.lib(ThirdPartyd.dll) : error LNK2005:
    "public: virtual __thiscall MyClass<42>::~MyClass<42>(void)"
    (??1?$MyClass@$01@@@UAE@XZ) already defined in Client.obj

Что мне делать?

Ответы [ 2 ]

4 голосов
/ 20 февраля 2010

Кажется, что для виртуальных методов необходимо определять их как extern и __declspec(dllimport) одновременно:

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

Это сделало мой компоновщик достаточно счастливым для правильной компоновки моего кода.

Я был бы очень рад, если бы какой-нибудь эксперт описал это или хотя бы указал на какую-то статью, объясняющую этот случай.

1 голос
/ 18 февраля 2010

Я считаю, что Visual Studio использует шаблонную специализацию в dll для некоторых конструкций stl. string приходит на ум,

Я быстро взглянул на файл заголовка, и похоже, что он использует

__declspec(dllimport)

по объявлению группы специализаций. Похоже, что это не так для всего класса.

Из этого обсуждения звучит так, как будто можно объявить весь класс экспортированным, но не сказано, как.

Извините за не столь полный ответ, но, надеюсь, это поможет вам изучить другие места.

...