I have some problems when I use JNA to call different .so in my program. It seems that my native shared libraries can't declare a method with the same name.
Example : I have a native1.c :
#include <stdio.h>
int anotherMethod() {
return 100;
}
int method() {
return 1 + anotherMethod();
}
And a native2.c :
#include <stdio.h>
int anotherMethod() {
return 200;
}
int method() {
return 2 + anotherMethod();
}
Each are compiled in a shared library (libnative1.so and libnative2.so).
$ gcc -m64 -shared -fPIC -o linux-x86-64/libnative1.so native1.c
$ gcc -m64 -shared -fPIC -o linux-x86-64/libnative2.so native2.c
(I am on a 64bit linux)
So invoking method() should return :
I will try it in a small Java Main :
public static void main(String[] args) {
Native1 native1 = (Native1) Native.loadLibrary("native1", Native1.class);
Native2 native2 = (Native2) Native.loadLibrary("native2", Native2.class);
System.out.println(native1.method());
System.out.println(native2.method());
}
The libraries interfaces are minimalists:
public interface Native1 extends Library {
int method();
}
And
public interface Native2 extends Library {
int method();
}
I obtain :
101 // OK
102 // Should be 202 !
It means the good method() invoked, but when my native code calls anotherMethod(), only the one from native1 is invoked.
I think Native.loadLibrary() loads my shared libraries and flatten it so only the first "anotherMethod" symbol exists.
In my real world case, the C code isn't under my responsibility, it is provided by another editor, so the less I have to edit it is the best
Is there a way to easily separate each shared library, like in a namespace or maybe a gcc option I missed out ?
When calling Native.loadLibrary()
, you can supply a Map
of options including the key Library.OPTION_OPEN_FLAGS
with a value corresponding to RTLD_LOCAL
. That should fix your issue.
Map options = new HashMap();
int RTLD_LOCAL = 0x4; // or whatever value it has on your platform
options.put(Library.OPTION_OPEN_FLAGS, RTLD_LOCAL);
Mylib lib = Native.loadLibrary("mylib", Mylib.class, options);
You can look up the value of RTLD_LOCAL
with grep RTLD_LOCAL /usr/include/*.h
on your target system.