What does "Symbol not found / Expected in: flat namespace" actually mean?
Description
The problem was caused by mixing objects that compiled with libc++
and object that compiled with libstdc++
.
In our case, the library myMod.so
(compiled with libstdc++
) need boost-python
that compiled with libstdc++
(boost-python-libstdc++
from now). When boost-python
is boost-python-libstdc++
, it will work fine. Otherwise - on computer that its boost-python
has compiled with libc++
(or another c++ library), it will have a problem loading and running it.
In our case, it happens because that libc++
developers intentionally changed the name of all of their symbols to prevent you (and save you) from mixing code from their library and code from a different one: myMod.so
need a function that take an argument from the type. In libc++
, this type's name is std::__1::pair
. Therefore, this symbol was not found.
To understand why mixing two version of the same API is bad, consider this situation: There are two libraries: Foo
and Bar
. They both have a function that takes a std::string
and uses it for something but they use a different c++ library. When a std::string
that has been created by Foo
will be passed to Bar
, Bar
will think that this is an instance of its c++ library's std::string
and then bad things can happen (they are a completely different objects).
Note: In some cases, there would be no problem with two or more different versions of the same API in a completely different parts of a program. There will be a problem if they will pass this API's objects between them. However, checking that can be very hard, especially if they pass the API object only as a member of another object. Also, a library's initialization function can do things that should not happen twice. Another version may do these things again.
How to solve that?
You can always recompile your libraries and make them match each other.
You can link
boost-python
to your library as a static library. Then, it will work on almost every computer (even one that doesn't hasboost-python
installed). See more about that here.
Summary
myMod.so
need another version of boost-python
, one that compiled with a specific c++ library. Therefore, It would not work with any another version.
In my case I was receiving:
ImportError: dlopen(/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/xmlsec.cpython-38-darwin.so, 0x0002): symbol not found in flat namespace '_xmlSecDSigNs'
BACKGROUND:
M1 MacBook Pro with Montery
I was working with a python virtualenv (using pyenv) to use an earlier version of python3.8 (3.8.2), while my system had 3.8.10 installed natively.
While I was in the activated 3.8.2 virtualenv I noticed the path in dlopen() was pointing to the package in the native python install NOT the virtualenv install.
SOLUTION:
In my case, I did not need the native 3.8 version at all so I simply removed it and this solved the problem.