2016-10-10 65 views
1

當我使用JNA在我的程序中調用不同的.so時,我遇到了一些問題。 看來,我的本地共享庫不能聲明一個同名的方法。JNA使用相同的方法名加載很多庫

實施例: 我有一個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)

所以調用方法()應返回:

  • 在native1
  • 202 101 native2

我會嘗試在一個小的Java主:

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選項?

+0

如果你使用C做同樣的事情,它會工作嗎?您也可以加載具有不同符號範圍的庫;默認情況下,它們使用'RTLD_GLOBAL'加載。用'RTLD_LOCAL'你可能會有更好的運氣(參見dlopen的手冊頁)。 – technomage

+0

對於主要使用dlopen,我可以調用方法沒有任何錯誤(打印101和202)。 但RTLD_GLOBAL選項產生相同的錯誤(101和102)。 您認爲在JNA中有模擬RTLD_LOCAL的方法嗎? – Lioda

回答

0

撥打電話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_LOCALgrep RTLD_LOCAL /usr/include/*.h值在目標系統上。

+0

是的,這是不錯的選擇。謝謝。在我的系統中,我必須使用值1(RTLD_LAZY + RTLD_LOCAL),它看起來不錯 – Lioda