Подтвердить что ты не робот

Что означает "Символ, не найденный/ожидаемый в: плоском пространстве имен", на самом деле означает?

Когда я импортирую модуль, который я построил, я получаю эту ошибку, связанную с boost-python:

Traceback (most recent call last):
  File "<string>", line 1, in <module>
ImportError: dlopen(./myMod.so, 2): Symbol not found: __ZN5boost6python7objects15function_objectERKNS1_11py_functionERKSt4pairIPKNS0_6detail7keywordES9_E
  Referenced from: ./myMod.so
  Expected in: flat namespace
 in ./myMod.so

Что это значит? Почему эта ошибка возникла?

4b9b3361

Ответ 1

Описание

Проблема была вызвана смешением объектов, скомпилированных с libc++, и объектов, скомпилированных с libstdc++.

В нашем случае библиотека myMod.so (скомпилированная с libstdc++) нуждается в boost-python, скомпилированном с libstdc++ (boost-python-libstdc++ с этого момента). Когда boost-python равен boost-python-libstdc++, он будет работать нормально. В противном случае - на компьютере, который boost-python скомпилировал с libc++ (или другой библиотекой c++), у него будут проблемы с загрузкой и запуском.

В нашем случае это происходит потому, что разработчики libc++ преднамеренно изменили имя всех своих символов, чтобы вы (и не могли спасти вас) не могли смешивать код из своей библиотеки и код из другой: myMod.so нужна функция, которая принимает аргумент из типа. В libc++ это имя типа std::__1::pair. Поэтому этот символ не был найден.

Чтобы понять, почему смешивать две версии одного и того же API плохо, рассмотрим следующую ситуацию: Есть две библиотеки: Foo и Bar. У них обоих есть функция, которая берет std::string и использует его для чего-то, но они используют другую библиотеку c++. Когда std::string, созданный Foo, будет передан Bar, Bar подумает, что это экземпляр его библиотеки c++ std::string, и тогда могут произойти плохие вещи (они являются совершенно разные объекты).

Примечание. В некоторых случаях не возникнет проблем с двумя или более разными версиями одного и того же API в совершенно разных частях программы. Будет проблема, если они передадут эти объекты API между ними. Однако проверить это может быть очень сложно, особенно если они передают объект API только как член другого объекта. Кроме того, функция инициализации библиотеки может делать то, что не должно происходить дважды. Другая версия может сделать это снова.

Как это решить?

  • Вы всегда можете перекомпилировать свои библиотеки и сделать так, чтобы они соответствовали друг другу.

  • Вы можете связать boost-python со своей библиотекой как статическую библиотеку. Затем он будет работать практически на каждом компьютере (даже на том, на котором не установлено boost-python). Подробнее об этом здесь.

Резюме

myMod.so нужна другая версия boost-python, которая скомпилирована с определенной библиотекой c++. Таким образом, он не будет работать с любой другой версией.

Ответ 2

Я сталкиваюсь с той же проблемой.

Expected in: flat namespace

Добавление флага компоновщика устраняет проблему

-lboost_python37

измените имя динамической библиотеки на имя, установленное в операционной системе.

Кстати, моя ОС MacOS High Sierra, и я использую brew для установки boost_python3.

Ответ 3

Вот что я узнал (osx):

Если это должно работать (т.е. работает на другом компьютере), вы можете столкнуться с проблемами clang/gcc. Чтобы отладить это, используйте otool -l в .so файле, который вызывает ошибку, или подозрительную библиотеку (в моем примере это файл dylib boost-python) и проверьте содержимое. Все, что находится в папке /System/, построено с помощью clang, и должно быть установлено где-то еще с компилятором gcc. Никогда не удаляйте ничего в папке/System.

Ответ 4

.so файлы - это динамические библиотеки (so = shared object). В Windows они называются .dll (динамическая библиотека). Они содержат скомпилированный код, который содержит функции, доступные для использования, любому исполняемому файлу, который их связывает.

Важно отметить, что те .so не являются файлами Python. Вероятно, они были скомпилированы из кода C или С++ и содержат публичные функции, которые могут быть использованы из кода Python (см. Документацию по Расширение Python с помощью C или С++).

В вашем случае, у вас есть поврежденный .so. Попробуйте переустановить уязвимые библиотеки, или Python, или и то, и другое.

Ответ 5

Символ, который не найден, означает, что определение объявленной функции или переменной не найдено. Когда файл заголовка общего объекта компилируется с вашей программой, компоновщик добавляет символы объявленных функций и объектов в вашу скомпилированную программу. Когда ваша программа загружается загрузчиком ОС, символы разрешаются так, чтобы их определение было загружено. Только в это время, когда реализация отсутствует, загрузчик жалуется, что не может найти определение из-за того, что может не решить фактический путь к библиотеке, или сама библиотека не была скомпилирована с файлом реализации/источника, где определение функции или объекта. В журнале linux есть хорошая статья http://www.linuxjournal.com/article/6463.