Introduction
前回は、自作のSharedライブラリに定義された関数をP/Invokeで呼び出してみました。
しかしながら、毎回毎回 /usr/local/lib とかにコピーするのってどうなんでしょう?
Windowsみたいに、実行ファイルと同じディレクトリにSharedライブラリを配置しても動作するのでしょうか?
Windowsの場合、exeが呼び出すdllは、実行ファイルから以下の順序で検索されます。
- 実行中のプロセスの実行形式モジュールがあるフォルダー。
- 現在のフォルダー。
- Windows システム フォルダー。
このフォルダーへのパスは、GetSystemDirectory 関数が取得します。 - Windows ディレクトリ。
このフォルダーへのパスは、GetWindowsDirectory 関数が取得します。 - 環境変数 PATH 内に記述されたフォルダー。
Linuxの場合、3,4以外は同じ条件で試すことができそうです。
ただ、.NET Coreの場合、dotnet runで動作する場合のカレントディレクトリに関して情報がないので、2もちょっと先送り。
最終的に下記の内容をテストしてみます。
- Sharedライブラリをシステムから削除
- Sharedライブラリを実行ファイルと同じフォルダに配置
- LD_LIBRARY_PATHと実行ファイルと同じフォルダの優先順位
Try
サンプルは、.NETでLinuxと遊んでみる Visual Studio Code編 第7回と同じものを使います。
Sharedライブラリをシステムから削除
これは動かないはずです。
実行ファイルと同じディレクトリ、/usr/local/lib64にSharedライブラリが存在しないことを確認してから実行してみます。
1 | sudo updatedb |
Windowsと同じように、System.DllNotFoundExceptionがスローされました。
期待通りです。
Sharedライブラリを実行ファイルと同じフォルダに配置
1 | pwd |
きちんと動作しました。
LD_LIBRARY_PATHと実行ファイルと同じフォルダの優先順位
これは気になりますね。
別に.NET Coreに関係なく、Linuxの仕組みと同じような気がしますが… 実行時、どちらが呼び出されたかわかるように、Sharedライブラリ側を修正します。
実行ファイルに配置するSharedライブラリ
1 |
|
/usr/local/lib64に配置するSharedライブラリ
1 |
|
これらをそれぞれビルドして、**/usr/local/lib64、実行ファイルと同じディレクトリである **bin/Debug/netcoreapp2.0/ にコピーします。
また、環境変数LD_LIBRARY_PATHに/usr/local/lib64を追加します。
一応、各ディレクトリにSharedライブラリがコピーされたことも確認しておきます。
そして、dotnet runで実行します。
1 | pwd |
結果としては、実行フォルダのSharedライブラリが優先されました。
また、実行フォルダのSharedライブラリを削除しても、/usr/local/lib64のSharedライブラリが使用され、きちんと動作することもわかりました。
Conclusion
結論としては、Windowsと同じく、実行ファイルのあるディレクトリに配置されているライブラリが優先のようですね。