缺失的符号来自一个动态库。

huangapple go评论91阅读模式
英文:

Missing symbols from a dylib

问题

我正在尝试在一个C++库周围创建一个C API,以便稍后在Golang中进行封装。我首先生成了一个带有一个函数的dylib,以便我有一个参考。然后我创建了一个包装器来使用实际的库。当我从简单的dylib生成所有符号时,我得到了这个:

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

我只声明了一个名为Hello的函数,目前还不错。

当我对实际的库做了我认为等效的操作时,Go封装器无法编译,生成的符号为:

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

我期望的符号是_SteamCAPI_Init(带有下划线,因为显然Hello生成了_Hello),但我得到了一些奇怪的东西。

是我的编译有问题,还是生成的符号正常?

源文件可以在这里找到(只有大约30行重要代码):
https://github.com/luxengine/steam
https://github.com/luxengine/steamc

编辑(供未来读者参考):

我写这篇文章时的问题是,我的头文件声明中有extern "C" {,但我的源文件没有,所以gcc会混淆名称,cgo找不到它。

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

I'm trying to make a C api around a C++ library, so that I can later wrap it in Golang. I started by simply generating a dylib with one function so that I have a reference to look at. Then I made a wrapper around the actual library I wanted to use. When I generated all the symbols from the simple dylib i got this:

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

and I only declared a single function named Hello, so far so good

When I did what i thought was equivalent for the actual library, the go wrapper wouldn't compile and the symbols generated where

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

The symbol I was expecting was _SteamCAPI_Init (with the underscore because apparently Hello generated _Hello but instead i get something weirdish.

Is my compilation wrong, or is that the normal symbol that should be generated ?

The source files are available here (theres only like 30 important lines):
https://github.com/luxengine/steam
https://github.com/luxengine/steamc

EDIT (for future readers):

my problem at the time of writing was that my header file declaration had the extern "C" { but my source file did not, so gcc would mangle the names anyway and cgo wouldn't find it.

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

答案1

得分: 1

首先,dyld_stub_binder是在编译C++时生成的默认符号,你不需要关心它。

其次,__Z14SteamCAPI_Initv实际上是正确的符号。由于C++支持函数重载,C++函数会使用混淆的符号名称进行编译,以避免函数名称之间的冲突。例如,你有两个函数void do_something(int a)void do_something(int a, int b),如果函数名称没有被混淆,链接器将如何解析符号名称。

关于C++名称混淆的信息可以在这里找到。

英文:

Firstly, dyld_stub_binder is the default generated symbol when you compile C++. You don't need to care about it.

Secondly, __Z14SteamCAPI_Initv is actually the right symbol. Since C++ supports overloading, C++ functions are compiled with mangled symbol names, so that the functions name won't clash with each other. For example, you got two functions void do_something(int a) and void do_something(int a, int b), if the function names are not mangled, how would the linker resolve symbol names.

Info about C++ name mangling can be found here.

huangapple
  • 本文由 发表于 2015年10月6日 09:58:53
  • 转载请务必保留本文链接:https://go.coder-hub.com/32960554.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定