2011-08-08 64 views
0

我試圖將非Qt靜態庫鏈接到基於Qt的應用程序(它的Visual Studio項目)。
問題是,靜態庫有一些API將指向TCHAR字符串的指針作爲其中一個輸入。 當我嘗試構建項目時,出現鏈接錯誤,抱怨TCHAR。從Qt應用程序鏈接到C++靜態庫

頁眉

class Test 
{ 
    public: 
    static bool TestFunc(TCHAR *empty); 
}; 

來源

bool Test::TestFunc(TCHAR *empty) 
{ 
    return true; 
} 

錯誤:

error LNK2019: unresolved external symbol "public: static bool __cdecl Test::TestFunc(unsigned short *)" ([email protected]@@[email protected]) referenced in function "public: __thiscall TestApp::TestApp(class QWidget *,class QFlags<enum Qt::WindowType>)" ([email protected]@[email protected]@@[email protected]@[email protected]@@@@Z) 

有趣的是,如果我在頭文件中的函數實現,它工作正常。或者,如果我將TCHAR更改爲常規字符並保持聲明/定義分開,它也可以工作(使用wchar_t直接失敗並具有相同的鏈接錯誤)。

有誰知道什麼可能導致這個問題,以及如何解決它?
由於提前,

回答

2

確保編譯器設置對於兩個項目中的相同。特別看看「字符集」屬性,確保它們都是Unicode。這改變了TCHAR宏的定義。

+0

嗨馬克,我確實在每個項目中將「字符集」屬性設置爲「使用Unicode」,並且在每個項目中,TCHAR被定義爲wchar_t。令人費解的是,我不確定爲什麼如果在頭文件中定義了定義,而不是在源文件中定義它,它會起作用。 – SL001

+0

@ SL001,如果在頭文件中有定義,鏈接器不需要嘗試在庫中找到它;這根本就不是神祕的。必須有某些東西阻止函數定義在庫中導出。 –

0

根據應用程序的構建方式,TCHAR可以是char或wchar(即utf16)。

編輯:如果你想與TCHAR
混合Qt的strign類型的QString的簡單轉換爲local8bitutf16(),然後把結果以TCHAR *

,並從TCHAR轉換回QString的

QString toQString(const char *str) { return QString::fromLocal8Bit(str); } 
QString toQString(const wchar_t *str) { return QString::fromWCharArray(str); } 
+0

嗨馬丁,在應用程序中,我使用unicode字符串,所以TCHAR被定義爲wchar_t(將字符集設置爲使用unicode,並驗證UNICODE在項目設置中是否正確定義)。我遇到的問題是靜態lib在其大多數API中使用TCHAR,所以雖然我可以使用Qts字符串功能將QString轉換爲TCHAR,但它給了我前面提到的鏈接器錯誤。謝謝, – SL001

3

什麼是靜態庫編譯使用?視覺工作室?什麼版本?

我會盡力解釋您遇到的問題。

首先,當你把函數體在頭它工作的原因,是因爲這本質上使函數體由您的應用程序進行重新編譯。鏈接器實際上不再需要從靜態庫中解析任何符號。 Ergo,鏈接器問題消失。

問題是,當編譯靜態庫時,它導出的函數Test::TestFunc被編譯器破壞了(它實質上是根據某個內部模式對其進行重命名)。函數名稱編譯是編譯器的工作,以簡化鏈接器的符號解析。根據C++標準沒有指定函數名稱被修改的方式。因此,打開不同設置的不同編譯器將對函數名稱進行不同的修改。

當您嘗試構建鏈接此庫的應用程序時,Visual Studio現在損壞了名爲(可能位於main())的函數。如果名稱重整靜態庫,其中的函數定義的,不匹配的名字來自函數被調用重整,那麼你得到你所收到的錯誤。也就是說,鏈接器將在靜態庫中查找功能X,並且它可以找到的所有功能都是功能Y

現在,正如其他海報所指出的那樣,這個名稱的改變也取決於函數作爲輸入的參數。如果參數類型在兩個地方(定義和用法)不同,編譯器將以不同方式對函數名稱進行壓縮。 Ergo,再一次,鏈接器將無法解決匹配。底線是,在符號存在的兩個地方(圖書館和應用程序),符號MUST必須相同。最好的方法是使用完全相同的編譯器進行編譯,並使用完全相同的設置。

另一種可能性當然是,符號實際上並不存在於您要鏈接的靜態庫中!

1

默認情況下,VS編譯時啓用「Treat wchar_t as Built-in Type」(/Zc:wchar_t)。 Qt編譯時禁用了該選項(/Zc:wchar_t-)。如果在VS中(在配置屬性> C/C++>語言下)禁用「將wchar_t作爲內置類型」,則在構建靜態庫之前,是否解決了這個問題?

+0

是,解決了它,謝謝。當我在靜態庫項目設置中禁用該設置時,它解決了我所看到的鏈接錯誤。那確實會導致第二個問題,那就是如何改變這種情況? – SL001

+0

我不認爲有任何後果;據我所知,這只是一個鏈接偏好,即API暴露的方式。重要的是選項匹配。 http://msdn.microsoft.com/en-us/library/dh8che7s(v=VS.90).aspx –