web-dev-qa-db-ja.com

「Symbol not found / Expected in:flat namespace」は実際にはどういう意味ですか?

ビルドしたモジュールをインポートすると、この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

これは実際にはどういう意味ですか?なぜこのエラーが発生したのですか?

24
kilojoules

説明

この問題は、libc++でコンパイルされたオブジェクトとlibstdc++でコンパイルされたオブジェクトが混在しているために発生しました。

この場合、ライブラリmyMod.solibstdc++でコンパイル)にはboost-python(今からlibstdc++)でコンパイルされたboost-python-libstdc++が必要です。 boost-pythonboost-python-libstdc++の場合、正常に動作します。それ以外の場合-boost-pythonlibc++(または別のc ++ライブラリ)でコンパイルされたコンピューターでは、ロードと実行に問題が発生します。

私たちの場合、libc++開発者が自分のすべてのシンボルの名前を意図的に変更して、ライブラリのコードと別のコードのコードを混在させないようにします(あなたを救います):myMod.so need a型から引数を取る関数。 libc++では、この型の名前はstd::__1::pairです。したがって、このシンボルは見つかりませんでした。

同じAPIの2つのバージョンを混在させるのがなぜ悪いのかを理解するために、次の状況を考慮してください。2つのライブラリ:FooBarがあります。両方ともstd::stringを取り、それを何かに使用する関数を持っていますが、異なるc ++ライブラリを使用します。 Fooによって作成されたstd::stringBarに渡されると、Barは、これがそのc ++ライブラリのstd::stringのインスタンスであると見なし、その後悪いことが起こる可能性があります(それらは完全に異なるオブジェクトです)。

:場合によっては、プログラムのまったく異なる部分にある同じAPIの2つ以上の異なるバージョンで問題が発生することはありません。このAPIのオブジェクトをそれらの間で受け渡す場合、問題が発生します。ただし、特にAPIオブジェクトを別のオブジェクトのメンバーとしてのみ渡す場合、チェックは非常に困難です。また、ライブラリの初期化関数は、2回発生してはならないことを実行できます。別のバージョンがこれらのことを再度行う場合があります。

それを解決する方法は?

  • ライブラリはいつでも再コンパイルして、互いに一致させることができます。

  • boost-pythonを静的ライブラリとしてライブラリにリンクできます。その後、ほぼすべてのコンピューター(boost-pythonがインストールされていないコンピューターでも)で動作します。詳細については こちら をご覧ください。

概要

myMod.soには、特定のc ++ライブラリでコンパイルされたboost-pythonの別のバージョンが必要です。したがって、他のバージョンでは機能しません。

18
Shmuel H.

同じ問題が発生します。

Expected in: flat namespace

リンカーフラグを追加して問題を修正

-lboost_python37

動的ライブラリ名をOSにインストールされている名前に変更します。

ちなみに、私のOSはmacOS High Sierraであり、brewを使用してboost_python3

4
zhaofeng-shu33

Symbol not foundは、宣言された関数または変数の定義が見つからなかったことを意味します。共有オブジェクトのヘッダーファイルがプログラムでコンパイルされると、リンカは宣言された関数とオブジェクトのシンボルをコンパイル済みプログラムに追加します。プログラムがOSのローダーによってロードされると、シンボルが解決され、定義がロードされます。現時点で、実装が欠落している場合、ローダーがライブラリへの実際のパスの解決に失敗している可能性があるため定義を見つけることができない、またはライブラリ自体が実装/ソースファイルでコンパイルされていないことを訴える関数またはオブジェクトの定義が存在します。これに関する良い記事がLinux Journalにあります http://www.linuxjournal.com/article/646

1
Misgevolution

これが私が学んだことです(osx):

これが動作するはずである場合(つまり、別のコンピューターで動作する場合)、clang/gccの問題が発生している可能性があります。これをデバッグするには、エラーを発生させている.soファイルまたは疑わしいライブラリ(この例ではboost-python dylibファイル)でotool -lを使用し、内容を調べます。/System /フォルダー内のすべてのものはclangで構築されているため、gccコンパイラーを使用して別の場所にインストールする必要があります。/Systemフォルダー内の何も削除しないでください。

1
kilojoules

.soファイルは動的ライブラリです(つまり=共有オブジェクト)。 Windowsでは、それらは.dll(ダイナミックリンクライブラリ)。それらには、それらをリンクする実行可能ファイルで使用できる関数を含むコンパイル済みコードが含まれます。

ここで重要なのは、それらの.soはPythonファイルではありません。これらはおそらくCまたはC++コードからコンパイルされ、Pythonコードから使用できるパブリック関数を含んでいます。 Extending Python with C or C++ )。

あなたの場合、まあ、あなたは壊れている.so。影響を受けるライブラリ、Python、またはその両方を再インストールしてみてください。

1
zvone