#java #jna
#java #jna
Вопрос:
У меня возникают некоторые проблемы, когда я использую JNA для вызова different .so в моей программе. Кажется, что мои собственные разделяемые библиотеки не могут объявить метод с тем же именем.
Пример: у меня есть native1.c :
#include <stdio.h>
int anotherMethod() {
return 100;
}
int method() {
return 1 anotherMethod();
}
И native2.c :
#include <stdio.h>
int anotherMethod() {
return 200;
}
int method() {
return 2 anotherMethod();
}
Каждый из них компилируется в общей библиотеке (libnative1.so и 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
(Я на 64-битном Linux)
Поэтому вызов метода () должен возвращать :
- 101 в native1
- 202 в native2
Я попробую это в небольшом 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());
}
Интерфейсы библиотек минималистичны:
public interface Native1 extends Library {
int method();
}
И
public interface Native2 extends Library {
int method();
}
Я получаю :
101 // OK
102 // Должно быть 202!
Это означает, что вызывается хороший метод(), но когда мой машинный код вызывает anotherMethod() , вызывается только метод из native1.
Я думаю, что Native.LoadLibrary() загружает мои разделяемые библиотеки и сглаживает их, чтобы существовал только первый символ «anotherMethod».
В моем реальном случае код C не находится под моей ответственностью, он предоставляется другим редактором, поэтому чем меньше мне нужно его редактировать, тем лучше
Есть ли способ легко разделить каждую разделяемую библиотеку, например, в пространстве имен или, может быть, в опции gcc, которую я пропустил?
Комментарии:
1. Работает ли это, если вы делаете то же самое с помощью C? Вы также можете загружать библиотеки с разными областями символов; по умолчанию они загружаются с
RTLD_GLOBAL
помощью . Возможно, вам повезетRTLD_LOCAL
больше (см. справочную страницу для dlopen).2. С помощью main, использующего dlopen, я могу вызывать методы без каких-либо ошибок (печатаются 101 и 202). Но опция RTLD_GLOBAL выдает ту же ошибку (101 и 102). Как вы думаете, есть ли способ имитировать RTLD_LOCAL в JNA?
Ответ №1:
При вызове Native.loadLibrary()
вы можете указать несколько Map
параметров, включая ключ Library.OPTION_OPEN_FLAGS
со значением, соответствующим RTLD_LOCAL
. Это должно решить вашу проблему.
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);
Вы можете посмотреть значение RTLD_LOCAL
with grep RTLD_LOCAL /usr/include/*.h
в вашей целевой системе.
Комментарии:
1. Да, это хороший вариант. Спасибо. В моей системе я должен использовать значение 1 (RTLD_LAZY RTLD_LOCAL), и это кажется хорошим