英文:
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论