2016-10-10 8 views
1

JNAを使用して自分のプログラムで異なる.soを呼び出すときにいくつか問題があります。 私のネイティブ共有ライブラリは同じ名前のメソッドを宣言できないようです。同じメソッド名を持つ多くのライブラリをロードするJNA

例:

#include <stdio.h> 
int anotherMethod() { 
    return 100; 
} 
int method() { 
    return 1 + anotherMethod(); 
} 

そしてnative2.c: 私はnative1.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

    でI意志小さな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のmanページを見てください)。 – technomage

    +0

    主にdlopenを使用すると、エラーなしでメソッドを呼び出すことができます(101と202が表示されます)。 しかし、RTLD_GLOBALオプションは同じエラー(101と102)を生成します。 JNAでRTLD_LOCALをシミュレートする方法があると思いますか? – Lioda

    答えて

    0

    Native.loadLibrary()を呼び出す場合は、RTLD_LOCALに対応する値のLibrary.OPTION_OPEN_FLAGSキーを含むMapのオプションを指定できます。それはあなたの問題を解決するはずです。

    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); 
    

    あなたは、ターゲットシステム上でgrep RTLD_LOCAL /usr/include/*.hRTLD_LOCALの値を調べることができます。

    +0

    はい、それは良いオプションです。ありがとうございました。私のシステムでは、値1(RTLD_LAZY + RTLD_LOCAL)を使用する必要があり、それは良いようです – Lioda

    関連する問題