0

I am using gcc/g++ on fedora 116, and my idea is:

c program -> load c++ dynamic library A -> load c++ dynamic library B

The c++ dynamic library B is third-party provided and I can not modify it.

When complinng c++ dynamic library A with linking c++ dynamic library B, A can find symbols in B. But when I load B functions in A code (not linking) using 'dlsym', A tells me

/path/to/B.so: undefined symbol: some_func

=============================

use nm -DC

0000000000014a80 T BinarySearch(int, int*, int)
0000000000007210 T CheckLicense()
0000000000009370 T GetEnd(stCha*, int&, int)
000000000000a970 T IC_Exit()
000000000000a740 T IC_Init(char const*)

the error report:

/path/to/some.so undefined symbol: IC_Init

the code in library A:

IC_API bool (* IC_Init)(const char *);
IC_Init = (IC_API bool (*)(const char *)) dlsym(dl_ic, "IC_Init");
if(IC_Init) {
    printf("function loaded");
}

in library A, it can load library B using dlopen:

void *dl_ic = dlopen(ic_lib_path, RTLD_LAZY);
Mickey Shine
  • 12,187
  • 25
  • 96
  • 148

1 Answers1

3

Have you considered name mangling? C++ identifiers are typically "mangled" to incorporate information on their namespace and arguments (which historically helped linkers differentiate overloaded functions). You may want to make the function extern "C" to prevent mangling, or find its mangled name to use with dlsym (e.g. on Linx use nm on an object, or gcc -S -o /dev/tty ... | grep some_func on the source).

Tony Delroy
  • 102,968
  • 15
  • 177
  • 252
  • what you mean "find its mangled name to use with dlsym"? Do you mean I have to use another name in 'dlsym' rather than the originally defined name? I have updated my question, please help check, thanks – Mickey Shine Mar 02 '12 at 08:33
  • or just take off the `-C` switch in the `nm` command the OP already posted, which will turn off the symbol-unmangling – araqnid Mar 02 '12 at 08:34
  • 1
    @Mickey: as araqnid pointed out, you're using the -C switch with nm, so that you get the readable function signatures you've used in your source code. Behind the scenes, the C++ compiler actually converts those to a tangle of underscores and alphanumerics, encoding the namespaces and/or class/struct scope the function appears as well as the argument types and member-function constness. That is the "real" symbolic name in the objects symbol table - the name you need to provide to dlsym. If you have `extern "C" IC_API bool IC_Init(const char *)`, the compiler won't mangle it. – Tony Delroy Mar 02 '12 at 09:13
  • To be more concrete: if I use g++ to compile a function `bool IC_Init(const char*)`, then use nm on the object to see the mangled name, it's actually `__Z7IC_InitPKc`. This is probably the name you need to ask dlsym to find, but you should check whether your compiler version has encoded it a little differently. You'll get more robust, version-independent code by using `extern "C"` to disable mangling. – Tony Delroy Mar 02 '12 at 09:17