2015-10-06 41 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