6

OSGiは私のDLLファイルを見つけることができず、その理由を理解できないようです。

foo.dll現在、バンドルのルートにDLLファイル( )がありますが、libsディレクトリにも入れてみました。

問題のバンドルのマニフェストは次のようになります。

Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: foobundle
Bundle-SymbolicName: com.foo.bar
Bundle-Version: 1.0.0
Bundle-Vendor: me
Import-Package: com.sun.jna,
 com.sun.jna.ptr,
 com.sun.jna.win32
Export-Package: com.foo.bar
Bundle-NativeCode: foo.dll;
 osname=WindowsXP;
 processor=x86

次に、JNAインターフェイスでloadLibraryを実行します(ドキュメントに従って)。

public interface MyFooInterface extends com.sun.jna.Library{
    static final MyFooInterface INSTANCE = (MyFooInterface)com.sun.jna.Native.loadLibrary("foo", MyFooInterface .class);

    // specific interface defs here...
}

次に、別のクラスでJNAインターフェイスを使用しようとします

// ...code
int var = MyFooInterface.INSTANCE.bar();
// ...more code

JNAを別のバンドル(com.sun.jnaと上記でインポートした他のパッケージをエクスポートする)で提供していますが、ここで定義したバンドルでパッケージ化してみました(その場合はクラスパスに追加しました)。

も指定してみましBundle-NativeCode: /foo.dllた。

また興味深いことに、これらは関連するOSGiプロパティです(私はこれを使用してプルアップしましたgetprop

org.osgi.framework.os.name=WindowsXP
org.osgi.framework.processor=x86

このすべての後でも(そして私が行ったすべての試行で)、私は常に次のエラー(およびスタックトレースは表示されていません)で終わります:

java.lang.UnsatisfiedLinkError: Unable to load library 'foo': The specified module could not be found.

...それで私は何が欠けていますか?

編集:私は、JNAインターフェイスコードと、JUnitテストプログラムの一部として通信するDLLをテストし、成功したことにも注意する必要があります。

編集2:ライブラリを呼び出しているクラスにこのコードを追加すると、JNAはライブラリを見つけることができるようです(Native.loadLibrary後で呼び出されたとき)。マニフェストのBundle-NativeCodeディレクティブに基づいて、この呼び出しを回避できるはずです。明らかに、ライブラリがロードされると、Native.loadLibraryはその既存のインスタンスを取得しますが、この非常に順序固有の戦術に依存したくないのです。

static{
    System.loadLibrary("foo");
}
4

4 に答える 4

7

問題は、OSGi に対応していない特殊な JNA loadLibrary 呼び出しです。OSGi バンドルから loadLibrary を呼び出すと、OSGi クラスローダー (バンドル対応) を使用して DLL の場所を見つけます。この場合、バンドルから抽出し、System.loadLibrary() を介してロード可能にします。特定の場所に対して呼び出します。

この JNA は (a) OSGi に対応しておらず、(b) 不要なように見えるため、代わりに System.loadLibrary() を使用しないのはなぜですか?

両方を記述する必要がある場合は、BundleActivator のバンドルの start() メソッドで System.loadLibrary() を実行します。これにより、ネイティブ ライブラリが取り込まれます (おそらく、ロードできない場合は、バンドルがいずれの場合も起動できません)。

于 2009-09-07T13:13:22.583 に答える
1

JNAのドキュメントを見ると、次のように記載されています。

  • ターゲット ライブラリを Java プログラムで使用できるようにします。これを行うには、次の 2 つの方法があります。
    • 推奨される方法は、jna.library.pathシステム プロパティをターゲット ライブラリへのパスに設定することです。java.library.pathこのプロパティは、JNA によってロードされたライブラリにのみ適用されますが、似ています。
    • VM を起動する前に、適切なライブラリ アクセス環境変数を変更します。これはPATH、Windows、LD_LIBRARY_PATHLinux、およびDYLD_LIBRARY_PATHOSX 上にあります。

したがって、この欠点を回避するには、ライブラリの絶対パスを解決してロードすることができます。

Eclipse の標準クラス ローダーであると仮定するとClassLoader.findLibrary()、バンドル内のローカル ライブラリを見つける必要があります。

于 2009-09-07T11:10:00.380 に答える
0

dll を jar としてパッケージ化することをお勧めします。

jar cvf foo.dll.jar foo.dll

jarを通常のlibとしてロードします。

于 2009-09-04T13:14:13.097 に答える