2

In a project environment, I wanted to change a source file for a shared object from c to cpp. I made sure to change its entry in the CMakeLists.txt, too:

add_library(*name* SHARED *mysource*.cpp)
target_link_libraries(*name as target* *item*)

The build process runs fine. Unfortunately, when I try to use it I get an error that the functions inside the .so can not be found.

After checking the dynamic symbol table inside the shared object with objdump -T, I found out that the names of the symbols differ from the ones in the source file. e.g.

int sr_plugin_init_cb(sr_session_ctx_t *session, void **private_ctx);

becomes

_Z17sr_plugin_init_cbP16sr_session_ctx_sPPv

Inside my visual studio code it says that it can build the object and link the shared library correctly, and it also changed from C to CXX in the output and gives me no errors even though some code is c++ only.

Why do the symbol names change?

Kevin
  • 16,549
  • 8
  • 60
  • 74
SiSc
  • 163
  • 9

2 Answers2

2

Why do the symbol names change?

C++ has a feature called function overload. Basically what happens is that you declare two function that are named the same, but slightly differ:

int sr_plugin_init_cb(sr_session_ctx_t *session, void **private_ctx);
int sr_plugin_init_cb(sr_session_ctx_t *session, void **private_ctx, int some_arg);

or a little worse case:

struct A {
    # each of these functions can be different depending on the object
    void func();
    void func() const;
    void func() volatile;
    void func() volatile const;
};

Functions are named the same. Linker doesn't see the C++ source, but it still has to differentiate between the two functions to link with them. So C++ compiler "mangles" the function names, so that linker can differentiate between them. For big simplicity it could look like:

sr_plugin_init_cb_that_doesnt_take_int_arg
sr_plugin_init_cb_that_takes_int_arg
A_func
A_func_but_object_is_const
A_func_but_object_is_volatile
A_func_but_object_is_volatile_and_const

The rules of name mangling are complicated, to make the names as short as possible. They have to take into account any number of templates, arguments, objects, names, qualifers, lambdas, overloads, operators etc. and generate an unique name and they have to use only characters that are compatible with the linker on a specific architecture. For example here is a reference for name mangling used by gnu g++ compiler.

The symbol name _Z17sr_plugin_init_cbP16sr_session_ctx_sPPv is the mangled by your compiler name of your function.

KamilCuk
  • 120,984
  • 8
  • 59
  • 111
1

Thank You very much for the detailled answer. I now understand the issue. After a quick search I found a solution for my problem. Encapsulating the function prototypes like this avoids the name mangling.

extern "C" {
    // Function prototypes
};
SiSc
  • 163
  • 9