2017-05-16 7 views
-1

NB:これは畳み込まれています。また、Windows用に設計されたレガシーソフトウェアで、C++標準/ Linuxと互換性を持たせるために移植しようとしています。私は、私が生産コードの例を挙げることができないので、私が問題を再現することができたいくつかの高いレベルの例を与えるつもりです。私たちがなぜこれを行うのか尋ねないでください。ただ私たちがやっていることを知っていて、私はそれに対処しなければなりません。共有ライブラリは共通インタフェースで実装されていますが、実装方法が異なる静的ライブラリにリンクしています

私たちには、共有ライブラリによって使用されるいくつかの静的ライブラリがあります。たとえば、FirstSharedLib.soとSecondSharedLib.soはどちらもCommonStaticLibrary.libに依存します。

ここでCommonStaticLibrary.libは、共有ライブラリによって実装されることを意図したメソッドを宣言します。例、GetSharedLibraryName();

したがって、FirstSharedLibプロジェクトは、 "FirstSharedLib"を返してCommonStaticLibraryのGetSharedLibraryNameを実装し、同様にSecondSharedLibは "SecondSharedLib"を返して実装します。

これは、たとえばFirstSharedLibがGetSharedLibraryName()を呼び出すときなど、ウィンドウで意図したとおりに動作します。 SecondSharedLibがGetSharedLibraryName()を呼び出すと、 "FirstSharedLib"文字列が受信されます。 "SecondSharedLib"文字列を受け取ります。

ダイナミックリンカは最初の共有ライブラリを読み込み、CommonStaticLibrary :: GetSharedLibraryName()の実装を見て、それをGetSharedLibraryName()を呼び出すすべての共有ライブラリに使用します。実際の実装に関係なく

したがって、FirstSharedLibが最初にロードされた場合は、GetSharedLibraryName()が呼び出されます。 "FirstSharedLib"文字列を受け取るが、SecondSharedLibが読み込まれると "FirstSharedLib"文字列も受け取られる。

また、SecondSharedLibが最初に読み込まれると、GetSharedLibraryName()のすべての呼び出しが "SecondSharedLib"を返します。

SecondSharedLibがGetSharedLibraryName()を呼び出すときに常にそのプロジェクトによって作成された実装を呼び出すように、静的ライブラリの共有された実装を事前リンクするためのリンカオプションはありますか?

共有ライブラリをロードするときに、メモリ内の固有の実装へのポインタが見えることに注意してください。他のライブラリが呼び出すたびに常に最初のロードされたインスタンス化が呼び出されます。

私たちはビルドシステムとしてCMakeを使用していますが、それはリンカーやコンパイラのフラグを渡すためにCMakeコマンドを使用するという事実以外にはあまり関係がありません。

共用ライブラリをコンパイルするために-fPICを使用してみましたが、共通ライブラリメソッドの可視性を非表示にしてアクセスを制限しようとしましたが、いずれのオプションも機能しませんでした。 Commonライブラリメソッドのシグニチャのいくつかを変更しようとしましたが、変更できる量は限られています。

+0

あなたはCommonStaticLibrary内のAPIは、各共有ライブラリに内部になりたい場合は、[可視]にGCCのwikiを見てください( https://gcc.gnu.org/wiki/Visibility)。デフォルトのWindowsとLinuxのビルドシステムの大きな違いの1つは、Linuxではすべてがデフォルトでエクスポートされるため、各ライブラリ間でシンボルが競合していることです。 –

+0

@ TavianBarnes、ありがとう、私たちはそれを試みました。私はCmake CMAKE_CXX_VISIBILITY_PRESETを "hidden"に設定し、 "-fvisibility = hidden"を明示的にコンパイラフラグに追加しました。いずれも顕著な効果はなかった。 – gnac

答えて

1

動的ライブラリをロードする私たちの方法では、コンパイル時に渡された隠し属性をオーバーライドしていたRTLD_GLOBALを渡していました。

RTLD_GLOBALフラグ(RTLD_LOCAL 0x0に置き換えられました)を削除しました。これで、ライブラリは静的ライブラリメソッドを共有ライブラリを起動するローカルに保ちます。また、フラグを削除して属性を非表示に設定することもできました。

古いコード:

int flag = RTLD_NOW | RTLD_GLOBAL; 
void* library = dlopen(libraryName, flag); 

新しいコード:

int flag = RTLD_NOW | RTLD_LOCAL; 
void* library = dlopen(libraryName, flag); 
関連する問題