私が過去に行った調査によると、ネイティブライブラリをロードする方法は2つしかありません。変更java.library.path
して使用する方法System.loadLibrary
(ほとんどの人がこれを行うように感じます)、またはSystem.load
絶対パスで使用する方法です。
ご存知のように、SBTとEclipseの構成に関しては、いじりjava.library.path
が煩わしい場合があり、実行可能jarに対して自動的に行うことはできないと思います。
だからそれは去るSystem.load
。独自のネイティブライブラリを作成するという点で、できることは次のとおりです。
javah
ネイティブソース(およびを使用gcc
)をコンパイルし、結果の.soファイルとそれに依存する.soファイルを取得し、それらをターゲットディレクトリのjarに(リソースとして)配置し、jarへのパスを追加するSBTタスクを作成します。にunmanagedJars in Compile
。
- ライブラリをロードするためのScalaメソッドを作成します。を呼び出す代わりに、ライブラリを読み取り、ファイルシステムのどこかに書き込み、JVMにロードするために
System.loadLibrary
使用します。Class.getResourceAsStream
File.createTempFile
System.load
System.loadLibrary
これで、以前のように呼び出す代わりに、を呼び出しますMyClasspathJniLoader.loadLibrary
。
これは、追加の構成なしでSBT実行、Eclipse、および実行可能jarで機能します(ただし、proguardがどのリソースを含めるかをどのように認識しているかはわかりません)。
すでに作成されているサードパーティのネイティブライブラリに関しては、jblasのような一部のライブラリはすでにこの「ファットジャー」アプローチを使用しています。彼らがあなたがセットアップすることを期待し、そして彼らがそれを感じたときに彼らがjava.library.path
電話をするならば、あなたはそれを機能させるためにいくつかの魔法をする必要があるでしょう。System.loadLibrary
私はこれを試していませんが、この解決策はうまくいくかもしれません:
- 同様のSBTタスクを使用して、ネイティブパス上のすべてのライブラリをリソースとしてjarに配置し、そのjarをclsaspathに配置します。
- 関数とライブラリ名のリストを受け取り、一時ディレクトリを作成し、それらのライブラリをjarのリソースから一時ディレクトリ内のファイルに読み取り、一時ディレクトリをに追加し
java.library.path
、渡された関数を呼び出し、最後に元に戻すScalaメソッドを作成します。java.library.path
以前の状態に戻ります。
- ネイティブライブラリを初めて呼び出すとき(おそらく静的に初期化して
System.loadLibrary
呼び出しを行うとき)、ロードするライブラリのリストを使用して、メソッド内の特定の呼び出しをラップします。そうすれば、を呼び出すとSystem.loadLibrary
、すべてのライブラリがオンにjava.library.path
なり、正常にロードされます。
java.library.path
サードパーティのライブラリを使用する前に手動で初期化する必要があるため、これは明らかに面倒ですが、すべてのツールを正しく設定するよりも、すべての初期化ポイント(メイン関数とテストの初期化)をラップする方が現実的です。。また、サードパーティのライブラリの上に独自の抽象化レイヤーがある場合は、それよりもさらに簡単な場合があります。そのため、ラップする必要のある初期化ポイントは実際には1つだけです。
それが現実的な解決策のように思われる場合は、混乱している場合は、SBTタスクまたはScalaラッパーメソッドに関する詳細を追加できます。