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

我通过另一个包(导出 com.sun.jna 和上面导入的其他包)提供了 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

问题是专门的 JNA loadLibrary 调用,它不支持 OSGi。当您从 OSGi 包调用 loadLibrary 时,它将使用 OSGi 类加载器(可识别包)来查找 DLL 的位置,在这种情况下,将其从包中提取出来并通过 System.loadLibrary() 使其可加载针对特定位置调用。

既然这个 JNA 似乎 (a) 不支持 OSGi,并且 (b) 是多余的,为什么不直接使用 System.loadLibrary() 呢?

如果你需要两者都写,那么在BundleActivator的bundle的start()方法中执行一个System.loadLibrary(),这将把原生库带进来(你可能要确保如果它不能被加载,bundle在任何情况下都无法启动)。

于 2009-09-07T13:13:22.583 回答
1

查看 JNA 的文档,它指出:

  • 使您的目标库可用于您的 Java 程序。有两种方法可以做到这一点:
    • 首选方法是将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 作为常规库加载。

于 2009-09-04T13:14:13.097 回答
0

com.sun.jna将包放在列表中是个好主意org.osgi.framework.system.packages.extra,因为本机库(例如jnidispatch.dll内部使用的com.sun.jna.Native)只能加载一次,而 OSGi 类加载器可以多次加载类。

于 2021-10-20T15:52:50.650 回答