JNA加载库
我有两个库,一个包含 Ada 对象,一个包含 C++ 对象(我对哪个库去哪里没有太多控制)
Ada 内容引用 C 内容,反之亦然...
这个符号位于 libIPCAda 中。所以: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
I've got two libraries, one with Ada objects and one with C++ objects (I don't have a lot of control about which goes where)
The Ada stuff references the C stuff and vice versa...
This symbol is in libIPCAda.so: ipc_manager_shutdown_c
This symbol is in libIPCC.so: stream_buffer_header_size
When I do these JNA Calls:
CLibrary INSTANCE8 = (CLibrary)
Native.loadLibrary("IPCAda", // <<< our library goes here
CLibrary.class);
CLibrary INSTANCE9 = (CLibrary)
Native.loadLibrary("IPCC", // <<< our library goes here
CLibrary.class);
I get this:
ld.so.1: java: fatal: relocation error: file <<my directory>>/lib/libIPCAda.so: symbol stream_buffer_header_size: referenced symbol not found
When I do these JNA calls:
CLibrary INSTANCE9 = (CLibrary)
Native.loadLibrary("IPCC", // <<< our library goes here
CLibrary.class);
CLibrary INSTANCE8 = (CLibrary)
Native.loadLibrary("IPCAda", // <<< our library goes here
CLibrary.class);
I get this:
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)
Obviously its not liking the cross dependent symbols... Is there any way to make this work in JNA?
*EDIT Example Compile *
gcc -c -fPIC -g -O0 -fstack-check -pipe -gnatE -gnatU -gnatwl -gnatf -gnatE -gnat05 -lIPCC -I- -gnatA <<my directory>>src/ndds_c.adb
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
交叉链接将发生在本机代码领域,而不是 Java 内部。据 JNA 所知,它正在加载两个完全独立的本机库。
您需要向图书馆本身提供彼此的位置。有几种方法可以做到这一点;可以在编译共享库时设置 rpath,也可以在运行时设置 LD_LIBRARY_PATH 环境变量。
Rpath 可以说是更好的方法,因为它特定于需要它的二进制文件,并且不会污染运行时环境。您可以使用以下编译器标志在 gcc 中设置它:
<代码>
-L 库路径 -Wl,-rpath,库路径
The cross-link is going to happen in native-code-land, not inside Java. As far as JNA knows, it's loading two completely independent native libraries.
You need to supply the libraries themselves with each others' locations. There are a couple ways to do this; either set the rpath when compiling the shared library, or set the LD_LIBRARY_PATH environment variable at run time.
Rpath is arguably the better method, since it's specific to the binary that needs it, and doesn't pollute the runtime environment. You can set it in gcc with the following compiler flags:
-Lpath-to-your-library -Wl,-rpath,path-to-your-library
您是否将所有原生关键字放入一个“CLibrary”中?因此,当它执行第一个 Native.loadLibrary 时,它会尝试将第一次加载中的所有符号映射到所有 Native 定义的方法。
尝试将其分解为 CLibrary1 和 CLibrary2,它们与将由 Ada 和 C 库加载的符号完全对应。我相信 Java 会尝试映射所有本机方法,并且会在第一个 Native.loadLibrary 缺少的一半上失败。
你还提到了C++。 Java JNI 无法加载 C++ 损坏的符号。如果您可能强制将实现导出为 C 符号,那么您就可以了。在谈论本机实现时,不要交换 C 和 C++。
Are you putting ALL your native keywords in a single 'CLibrary'? So when it does the first Native.loadLibrary it tries mapping all of the symbols from the first load to all of your Native defined methods.
Try breaking it up in to CLibrary1 and CLibrary2, where they correspond exactly to the symbol that will get loaded by the Ada and C libraries. I believe Java will try mapping all of your native methods and will fail on the half that is missing from the first Native.loadLibrary.
You also mention C++. Java JNI cannot load C++ mangled symbols. If you perhaps forced the implementation to export as C symbols instead you'll be ok. Don't exchange C and C++ when talking about native implementations.