JNA加载库

时间:2011-05-25 18:35:15

标签: java c++ java-native-interface shared-libraries jna

我有两个库,一个带有Ada对象,另一个带有C ++对象(我没有很多关于哪个库的控制权)

Ada的东西引用了C的东西,反之亦然......

此符号位于libIPCAda.so中: ipc_manager_shutdown_c

此符号位于libIPCC.so中: stream_buffer_header_size

当我执行这些JNA呼叫时:

   CLibrary INSTANCE8 = (CLibrary)
   Native.loadLibrary("IPCAda", //  <<< our library goes here
                      CLibrary.class);

   CLibrary INSTANCE9 = (CLibrary)
   Native.loadLibrary("IPCC", //  <<< our library goes here
                      CLibrary.class);

我明白了:

ld.so.1: java: fatal: relocation error: file <<my directory>>/lib/libIPCAda.so: symbol stream_buffer_header_size: referenced symbol not found

当我执行这些JNA调用时:

   CLibrary INSTANCE9 = (CLibrary)
   Native.loadLibrary("IPCC", //  <<< our library goes here
                      CLibrary.class);

   CLibrary INSTANCE8 = (CLibrary)
   Native.loadLibrary("IPCAda", //  <<< our library goes here
                      CLibrary.class);

我明白了:

Exception in thread "main" java.lang.UnsatisfiedLinkError: Unable to load library 'IPCC': ld.so.1: java: fatal: relocation error: file <<my directory>>/lib/libIPCC.so: symbol ipc_manager_shutdown_c: referenced symbol not found
    at com.sun.jna.NativeLibrary.loadLibrary(NativeLibrary.java:163)
    at com.sun.jna.NativeLibrary.getInstance(NativeLibrary.java:236)
    at com.sun.jna.Library$Handler.<init>(Library.java:140)
    at com.sun.jna.Native.loadLibrary(Native.java:379)
    at com.sun.jna.Native.loadLibrary(Native.java:364)
    at Test2$CLibrary.<clinit>(Test2.java:55)
    at Test2.main(Test2.java:74)

显然它不喜欢交叉依赖的符号......有没有办法在JNA中使这个工作?

* 编辑示例编译*

gcc -c -fPIC -g -O0 -fstack-check -pipe -gnatE -gnatU -gnatwl -gnatf -gnatE -gnat05 -lIPCC -I- -gnatA <<my directory>>src/ndds_c.adb

2 个答案:

答案 0 :(得分:6)

交叉链接将发生在native-code-land中,而不是Java中。据JNA所知,它正在加载两个完全独立的本机库。

您需要将库自己提供给彼此的位置。有几种方法可以做到这一点;在编译共享库时设置rpath,或在运行时设置LD_LIBRARY_PATH环境变量。

Rpath可以说是更好的方法,因为它特定于需要它的二进制文件,并且不会污染运行时环境。您可以使用以下编译器标志在gcc中设置它:

-Lpath-to-your-library -Wl,-rpath,path-to-your-library

答案 1 :(得分:1)

您是否将所有原生关键词放在一个'CLibrary'中?因此,当它执行第一个Native.loadLibrary时,它会尝试将所有符号从第一个加载映射到所有Native定义的方法。

尝试将其分解为CLibrary1和CLibrary2,它们完全对应于将由Ada和C库加载的符号。我相信Java会尝试映射所有本机方法,并且会在第一个Native.loadLibrary中缺少的一半上失败。

CLibrary INSTANCE9 = (CLibrary)
Native.loadLibrary("IPCC", //  <<< our library goes here
                  CLibrary.class);

AdaLibrary INSTANCE8 = (AdaLibrary)
Native.loadLibrary("IPCAda", //  <<< our library goes here
                  AdaLibrary.class);

你还提到了C ++。 Java JNI无法加载C ++损坏的符号。如果您可能强制将实现导出为C符号,那么您就可以了。在谈论本机实现时,不要交换C和C ++。