0

I'm working on C++ code called, via pybind11, from a Python (v3.8) application on Ubuntu 20.04.

Running the application I get an error

Traceback (most recent call last):
snip...
ImportError: <full-path>/<lib-name-A>.so: undefined symbol: <mangled symbol name>

ldd on lib-name-A output gives the absolute path to lib B in which the symbol is defined. nm -s --demangle on lib B shows the symbol is defined in the text section. Just to be sure, I compared the mangled name, and the one in lib B is identical to the one given in the error message.

So, given the library exists where ldd shows its expected, and the symbol is defined in it, why do I get the error message?

Uri Raz
  • 435
  • 1
  • 3
  • 15
  • 1
    Are you sure the environments are identical between your failing Python application and your ldd application? For example, the variable LD_LIBRARY_PATH may be different? Does using LD_DEBUG=files show the libraries your failing Python application loads are the ones you expect? – Stephen M. Webb Oct 10 '21 at 12:24

1 Answers1

1

nm -s --demangle` on lib B shows the symbol is defined in the text section

The function being defined in lib B is necessary, but not sufficient. The function must also be exported from lib B.

Chances are, it's not. To verify, run:

nm -D /path/to/lib-B.so | grep $mangled_symbol_name_here

If my guess is correct (function is not exported), you will get no output from above command.

Update:

Checking with nm -D, and the symbol is missing. Checking again with -s, the symbol has t (lowercase) next to it, rather than T

Ok, so my guess was correct.

I've added __attribute__((visibility("default"))) in front of the function declaration,

That's the correct solution.

Question is why I need to declare it explicitly as visible.

Most likely because you are building this code with -fvisibility=hidden, which says "hide everything not explicitly declared as visible".

Building with -fvisibility=hidden is current best practice, but you do need to mind which symbols are used outside of the shared library you are building.

Employed Russian
  • 199,314
  • 34
  • 295
  • 362
  • Checking with nm -D, and the symbol is missing. Checking again with -s, the symbol has t (lowercase) next to it, rather than T. So I've added __attribute__((visibility("default"))) in front of the function declaration, which solved the problem. The function is not a class member, but rather defined in a pre-existing namespace. Seems to me the only difference between the new function and functions written before is the use of a parameter of pybind11 type. Question is why I need to declare it explicitly as visible. – Uri Raz Oct 11 '21 at 12:33