2011-06-17 54 views
2

我正在使用Visual Studio 2008構建的C++項目。 我正在定義(在生成dll的項目中)模板類和派生的非模板類:類擴展模板類的C++符號導出

template <class T> 
struct DLL_EXPORT Base { 
    int base() { return 1; } 
}; 

struct DLL_EXPORT Deriv: public Base<Deriv> { 
    int deriv() { return 1; } 
}; 

DLL_EXPORT是平常的東西:

#ifdef COMPILING_MY_DLL 
    #define DLL_EXPORT __declspec(dllexport) 
#else 
    #define DLL_EXPORT __declspec(dllimport) 
#endif 

現在,當我試圖用我的Deriv類在另一個項目,麻煩開始。如果我只使用功能從Deriv,它工作得很好:

Deriv d; 
d.deriv(); 

但是,如果我嘗試調用d.base(),我得到下面的連接錯誤:

error LNK2019: unresolved external symbol "__declspec(dllimport) public: int __thiscall Base<struct Deriv>::base(void)" ([email protected][email protected]@@@@QAEHXZ) 

如果其他地方在我的DLL的代碼,我正在使用d.base()函數,它運行良好,鏈接器錯誤在「用戶」項目中消失。如果我刪除了模板部分(在我的例子中它不是非常有用,但是在真實情況下),一切都很好。

它看起來像函數沒有被編譯,如果它沒有被使用,或者等價的東西。任何想法 ?

在此先感謝。

回答

2

我不知道很多關於這一點,但我想你也許可以修復它通過在源文件中寫

template struct Base<Derive>; 

地方。 (或者template DLL_EXPORT struct Base<Derive>;

+0

是的,這很有效!謝謝。 DLL_EXPORT是不需要的,你甚至可以說'模板Base '(沒有struct關鍵字) – Xavier 2011-06-17 16:06:56

3

如果這是你的問題,你可以通過explicitly instantiating the template修復它。

在你的DLL中的.cc文件之一(不是頭文件),包括你的模板定義,並寫上:

template int Base<Deriv>::base(); 

這應該強制編譯器把代碼Base<Deriv>::base()成編譯單元,你的鏈接器可以找到它。

+0

我不確定它,但我認爲這不會輸出名稱Base :: base() – 2011-06-17 02:28:28

+0

@Edwin:我會好奇的知道。該類被聲明爲「dllexport」,因此編譯器可能會在這裏做正確的事情。 – Nemo 2011-06-17 02:49:24

+0

你是100%的權利。把你的建議放在一個dll源文件中,並且鏈接OK。 (沒有想到) – 2011-06-17 15:12:22

3

因爲模板定義沒有導出(它們在實例化之前它們不是實際代碼),所以不要在模板定義上使用__declspec(dllexport)。 它們只在頭文件中供源使用。您可以在模板的特化中使用__declspec(dllexport),但您必須在DLL中至少安裝一次。

+0

感謝評論,即使它沒有解決問題,我沒有想到這一點。 – Xavier 2011-06-17 15:53:18

+0

對於可憐的靈魂來到這裏:這個答案可以解決您的問題,如果使用MinGW。無論你在子類/ DLL中做什麼,如果Base模板類具有'__declspec(dllexport)',你將會*有鏈接時間錯誤。 – 2016-06-13 09:11:19