オープンソース アプリケーション (APP と呼びましょう)、クローズド ソース共有ライブラリ (OPENGL と呼びましょう)、OPENGL 用のオープン ソース プラグイン (PLUGIN と呼びましょう) [共有ライブラリとも呼びます] の 3 つがあります。
OS: リナックス。
APPとPLUGINの間でデータを共有する必要があるため、APPはPLUGINとリンクし、実行するとシステムが自動的にロードします。
その後、APP は OPENGL に属する eglInitialize を呼び出し、その後、この関数は PLUGIN を再度ロードします。
その後、APPメモリにPLUGINの2つのコピーがあります。
PLUGIN のおかげでグローバル データがあることはわかっています。デバッグ後、グローバル データのコピーが 2 つあることがわかりました。
では、この動作を修正するにはどうすればよいでしょうか? APP と OPENGL で使用される PLUGIN の 1 つのインスタンスが必要です。また、OPENGL ライブラリを変更できません。
2 に答える
それは明らかに、ライブラリが何をしているかに大きく依存しますが、一般的には何らかの解決策が可能なはずです。
最初に、通常、同じ名前の共有ライブラリが複数回ロードされた場合、同じライブラリを引き続き使用することに注意してください。これは主に、標準のローディング/リンク メカニズムを介したローディングに適用されます。dlopen
ライブラリが独自に呼び出す場合でも、同じライブラリを取得できますが、フラグに依存しdlopen
ます。dlopen のドキュメントを読んで、dlopen がどのように機能し、どのように操作できるかを理解してください。
PLUGIN をリンカ コマンドの早い段階で配置して、最初に読み込まれるようにして、後の二重読み込みを回避することもできます。PLUGIN を動的にロードする必要がある場合、これは明らかに役に立ちません。LD_PRELOAD
リンク順序を解決できるかどうかを確認することもできます。
最後の手段としてLD_LIBARY_PATH
、実際のライブラリからインターフェイス ライブラリを使用して配置する必要がある場合があります。これは単純に呼び出しを実際の呼び出しに渡しますが、重複したロードをインターセプトし、それらを前のロードにシャントします。
これは、考慮すべき一般的な方向性です。実際の答えは、コードと他の共有ライブラリの機能に大きく依存します。他のオプションに入る前に、リンカのロード順序を最初に調べてください。
OPENGL がRTLD_LOCAL
フラグ付きの PLUGIN をロードしていると思われます。これは通常、複数のプラグインが競合しないように、プラグインをロードするときに必要なものです。
Java でコードをロードする際にも同様の問題がありました。十数個の異なるモジュールをロードすると、それらは互いに通信できなくなりました。私たちのソリューションがうまくいく可能性があります。私たちはプラグインのラッパーを作成し、ラッパーがプラグインであることを Java に伝えました。そのプラグインは、 with を使用dlopen
して、他の共有オブジェクトをそれぞれロードしましたRTLD_GLOBAL
。これはプラグイン間で機能しました。ただし、プラグインがメインに戻ることができるかどうかはわかりません(ただし、そうすべきだと思います)。また、IIRC では、main をリンクしてそのシンボルを使用できるようにするときに、特別なオプションが必要になります。Linux は main のシンボルを、main が別の方法でロードされたかのように扱うと思いRTLD_LOCAL
ます。(たぶん
--export-dynamic
?これをしなければならなかったのは久しぶりで、正確には思い出せません。)