web-dev-qa-db-ja.com

実行時に共有ライブラリをパスでロード

Java C++で記述され、さまざまなオペレーティングシステム用にコンパイルされた共有ライブラリを使用するアプリケーションを構築しています。問題は、この共有ライブラリ自体が、適切な場所で通常見つける追加のライブラリに依存していることです。環境変数(PATHLIBRARY_PATHまたはLD_LIBRARY_PATH)。

これらの環境変数を設定することはできますが、したくありません。プラグインのように、必要な共有ライブラリを実行時に特定のパスからロードしたいのです。そして、いいえ-新しい環境で新しいプロセスを開始するスターターアプリケーションは必要ありません。誰かがこれを達成する方法を知っていますか?

私が使用するライブラリの1つは、指定されたパスからプラグインをロードできるため、これが可能でなければならないことを知っています。もちろん、プラットフォームに依存しないコードを使用したいと思いますが、これが不可能な場合は、Windows、Linux、およびMacOS用の個別のソリューションでも実行できます。

[〜#〜] edit [〜#〜]使用したい共有ライブラリはオブジェクト指向であることを述べたはずです。つまり、単一の関数をバインドしても機能しません。

25
aRestless

UNIX/Linuxシステムでは、dlopenを使用できます。問題は、dlsymを介して必要なすべてのシンボルをフェッチする必要があることです。

簡単な例:

typedef int (*some_func)(char *param);

void *myso = dlopen("/path/to/my.so", RTLD_NOW);
some_func *func = dlsym(myso, "function_name_to_fetch");
func("foo");
dlclose(myso);

.soをロードし、そこからfunction_name_to_fetch()を実行します。詳細については、manページのdlopen(1)を参照してください。

31
johannes

WindowsではLoadLibrary、Linuxではdlopenを使用できます。 APIは非常によく似ており、フルパスを指定することでso/dllを直接ロードできます。これは、実行時の依存関係である場合に機能します(ロード後、GetProcAddress/dlsymを呼び出して「リンク」します)。

13
Anteru

DlopenとLoadLibraryの使用について他のポスターにも同意します。 libltdl は、これらの関数へのプラットフォームに依存しないインターフェースを提供します。

6
thiton

あなたはそれのためにそれを行うことができるとは思わない。

ほとんどのDLLには、読み込まれた後に呼び出す必要があるinit()関数があり、そのinit()関数にはいくつかのパラメーターが必要で、dllの関数を呼び出すために使用するハンドルを返します。追加ライブラリの定義を知っていますか?

次に、最初のライブラリは、DLL XがRAMにその名前を使用するだけであるかどうかを確認します。必要なものは別のディレクトリにある可能性があります。または別のビルド/バージョンフルパスがすでにロードされている別のパスと同じである場合、OSはライブラリを認識し、2回目にロードするのではなく共有します。

他のライブラリは、PATHに依存しないように書かれており、それらは彼自身のプラグインであるため、別のパスからプラグインをロードできます。

DLLをロードする前に、コードからプロセスの環境変数を更新しようとしましたか?それはスタータープロセスに依存しません。

0
PRouleau