JNA загрузка многих библиотек с одинаковым именем метода

#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), и это кажется хорошим