2011-08-21 61 views
1

我正在嘗試爲諸如win32,mac os,linux,iOs等平臺創建一個抽象層。我想要這個動態鏈接。在不支持的平臺上,它不應該成爲一個問題,因爲從我看到的所有可以編譯爲動態庫的內容都可以編譯爲靜態庫,並且對代碼的影響最小。關於C++命名約定的問題

現在去的這點:

我創建了一個名爲IThread接口和一個名爲CThread類。我使用了一個名爲CreateThread的函數,該函數使用extern「C」定義,以便能夠將其導出並在庫外調用它。這裏的問題是,在win32中,例如已經有一個名爲CreateThread的函數,因此我得到一個鏈接器錯誤。我瞭解錯誤以及它出現的原因,但我不確定避免這種情況的好方法。我並不喜歡使用奇怪的命名,像CreateQtThread一樣使用qt。
我的另一個想法是創建一個創建CThread實例的線程管理器/工廠,但我不確定這將是一個好主意。

你們對此有何看法?我在問,因爲我不想衝這樣的重要組織問題。

非常感謝您

+2

你的問題是什麼?你明白錯誤,你不想重命名你的函數,所以你想知道我們對此有何看法? –

+0

是的,如果可能的話,我希望有更多經驗的人員就此發表意見。謝謝。 – Sanctus2099

+0

是否希望您的抽象層僅用於C++或其他語言(如C)?你是否想從給定的C++編譯器使用它(並且如果你需要改變編譯器,則重新編譯你的抽象層)或者oyu是否需要「一旦編譯一次就可以編譯C++」? – ysdx

回答

5

我用一個與外部的「C」定義爲能夠出口,並把它稱爲庫之外的功能命名的CreateThread。

這很糟糕。我無法談論其他平臺,但在Windows上,導出C++函數是完全正確的。他們只是被打亂了,你會得到一些理智的檢查,以防有人改變聲明。實際上,這是導出一個函數的唯一正確方法,即 C++。如果你將它聲明爲extern「C」,那麼你不會得到命名空間,也不會超載,如果異常從你的函數中退出,那麼編譯/EHsc的人將會遇到麻煩。

首選解決方案:不要將它們聲明爲extern「C」,並將它們放在名稱空間中。

唯一的其他解決辦法:好,你猜爲什麼所有的C庫前綴它們的職能處理their_lib_prefix_function ...

+0

爲什麼我使用extern「C」有一個很好的理由。如果我用Visual Studio 2010編譯DLL,那麼我可以在Visual Studio 2008中使用DLL,而無需重新編譯整個事情。實際上,我可以給某人DLL和必要的包含文件(接口),並且該人員可以在沒有實際源文件的情況下使用dll編譯項目(因爲函數的名稱沒有被損壞)。 – Sanctus2099

+0

@Sanctus:我認爲你的理解是錯誤的。 AFAIK在過去的10年裏,這個加工方案並沒有改變。 – ybungalobill

+0

我不確定它是否在不同版本的visual studio之間有所不同,但在不同的編譯器如gcc上有所不同。這裏有一個表格顯示了這個:http://en.wikipedia.org/wiki/Name_mangling – Sanctus2099

5

你使用的extern「C」的決定是合理的,我認爲,因爲它允許從其他語言訪問,編譯器等。但是這樣做意味着你不能使用命名空間,所以你只需要在你的函數前添加一些東西來標識它們來自你的庫,一個窮人的命名空間,如果你願意的話。

這是如果你想使用extern「C」必須做出的折衷。

5

嗯,我不知道你是否會喜歡這個,因爲我知道我與之合作的C開發人員發現它不美觀。但是,它非常簡單並且可以防止這樣的碰撞。 (或多或少地在this answer中用「their_lib_prefix_function」註釋提到)。

因此,無論何時我使用C代碼,我都會使用下劃線來基本'命名空間'我的函數。所以,假設你的名字空間是MegaAbstraction,那麼類似CreateThread就變成了MegaAbstraction_CreateThread。十分簡單。除非別人有名爲MegaAbstraction的命名空間,在這種情況下,我建議找到一個不太可能被其他人使用的命名空間。;)

+0

我的+1,我認爲那簡單而優雅。我並沒有發現有點迂腐,堅持要有相同的函數名稱,如下所示:1.只要函數名稱有意義,就沒有關係。 2.在一個實際的項目中,有100多個&1000的事情在爲命名具有特定名稱的函數而煩惱。 –

+0

:)謝謝,兩點都完全同意你的看法。而且,你知道可怕的是,我認爲我與之合作的那些人不喜歡我的命名規則,他們擔心......他們需要輸入多少額外的信件。 :DI的意思是,我以前在使用這些超長的描述性名稱時甚至是時髦的,儘管我已經削減了一點自己,我的意思是......如果你正在查看他們的代碼,那麼它應該是顯而易見的給你什麼kfifl()的意思,如果你不能區分kfifs()和kfifc()和kfifj()的含義,那麼這就是你的問題,而不是他們的問題。聳肩。 – shelleybutterfly

+0

我會留下我討厭與這樣的人一起工作。我相信一個很好的來源就是那個簡單明瞭,能夠被下一個在其中工作的人理解的來源。編寫令人討厭的代碼,除了作者所理解的沒有人是真正的維護噩夢。哎呀! –

1

您的CreateThread使用stdcall調用約定(又名WINAPI)嗎?如果使用cdecl調用約定,則應該將函數名稱導出爲_CreateThread,並避免與Win32 CreateThread函數的鏈接衝突。

extern "C" _declspec(export) int _cdecl CreateThread(... 
0

在Qt中沒有「CreateQtThread」函數,甚至沒有類似的東西。有一個QThread類,它有構造函數。如果需要,您可以將所有內容放入命名空間中。