2015-10-06 40 views
1

我正在嘗試在C++庫上做一個C api,以便後來可以將它包裝在Golang中。我從一個函數簡單地生成一個dylib開始,以便我可以參考一下。然後我圍繞我想要使用的實際圖書館做了一個包裝。當我產生的所有符號從簡單dylib我得到這個:dylib丟失的符號

MacbookMainframe:c hydroflame$ nm -a clib/libxyz.dylib 
0000000000000f90 T _Hello 
       U dyld_stub_binder 

,我只聲明瞭一個名爲Hello單一的功能,到目前爲止好

當我做了我認爲是等同於實際圖書館,去包裝不會編譯因爲產生顯然Hello產生的符號,其中

MacbookMainframe:c hydroflame$ nm -a ../luxengine.net/steamc/libsteam.dylib 
       U _SteamAPI_Init 
0000000000000f60 T __Z14SteamCAPI_Initv 
       U dyld_stub_binder 

我所期待的象徵是_SteamCAPI_Init(帶下劃線,但我得到了一些奇怪的東西。

我的編譯錯了,還是應該生成的正常符號?

的源文件都可以在這裏(孤單隻喜歡30重要行):
https://github.com/luxengine/steam
https://github.com/luxengine/steamc

EDIT(對於未來的讀者):

我在寫作的時候問題是我的頭文件聲明有extern "C" {,但我的源文件沒有,所以gcc無論如何都會破壞名稱,cgo不會找到它。

MacbookMainframe:steamc hydroflame$ nm -a libsteam.dylib 
       U _SteamAPI_Init 
0000000000000f60 T _SteamCAPI_Init 
       U dyld_stub_binder 

回答

1

首先,dyld_stub_binder是當編譯的C++缺省生成的符號。你不需要關心它。

其次,__Z14SteamCAPI_Initv實際上是正確的符號。由於C++支持重載,因此C++函數會使用錯亂的符號名稱編譯,以便函數名稱不會相互衝突。例如,您有兩個函數void do_something(int a)void do_something(int a, int b),如果函數名稱未被改變,鏈接器將如何解析符號名稱。

關於C++名稱修改的信息可以在here找到。

+0

嗯,即使我'出口「C」好吧...... bool SteamCAPI_Init ...}'?因爲這就是我在做的事情,所以認爲它不會破壞名字。如果是的話,有什麼方法可以不用修改它們,所以編譯器可以通過'SteamCAPI_Init'來獲取名稱? – user2475269

+0

導出「C」是爲了讓C知道函數是C++,它不影響編譯。 – Krypton

+0

如果您希望該符號爲「SteamCAPI_Init」,則需要爲'__Z14SteamCAPI_Initv'創建C封裝器。 – Krypton