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
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.