2017-10-05 82 views
1

簡而言之:顯然,本地方法必須在發出loadLibrary調用的同一類中聲明。如果本地方法在靜態內部類中聲明,則綁定失敗。java loadlibrary和本地方法聲明

工作例如:

public class TestNative 
{ 
    public TestNative() 
    { 
     System.loadLibrary("mylibrary"); 
    } 

    private native int nativeMethod(); 

    public void doit() 
    { 
     new NativeWrap().callNative(); 
    } 

    class NativeWrap 
    { 
     int callNative() 
     { 
      return nativeMethod(); // <<<< works 
     } 
    } 
} 

失敗例子:

public class TestNative2 
{ 
    public TestNative2() 
    { 
     System.loadLibrary("mylibrary"); 
    } 

    public void doit() 
    { 
     new NativeWrap().callNative(); 
    } 

    static class NativeWrap 
    { 
     int callNative() 
     { 
      return nativeMethod(); // <<<< throws UnsatisfiedLinkError 
     } 

     private native int nativeMethod(); 
    } 
} 

BTW:該作品調用LoadLibrary在這兩個例子。

我沒有發現任何有關此主題的提示。我發現的所有JNI示例都會在聲明本地方法的同一類中加載庫。有人能對這個東西發光嗎?

+0

如果你沒有在你的構造函數類TestNative2加載庫,而是在靜態塊加載它,會發生什麼? –

回答

1

它工作得很好。放置圖書館的地方並不重要。這裏重要的是方法的名稱。如果您生成方法簽名,然後將您的方法移到其他地方,它將無法運行。

到這裏看看:

package recipeNo001; 

public class HelloWorld { 

    static { 
    System.loadLibrary("HelloWorld"); 
    } 

    private native void displayMessage(); 

    static class NativeWrapper { 
    void callNative() { 
     displayMessageInner(); 
    } 
    private native void displayMessageInner(); 
    } 

    public static void main(String[] args) { 
    new HelloWorld().displayMessage(); 
    new NativeWrapper().callNative(); 
    } 
} 

但你必須確保你的內部庫提供正確的名稱。注意兩者之間的區別:

JNIEXPORT void JNICALL Java_recipeNo001_HelloWorld_displayMessage 
    (JNIEnv *env, jclass obj) 
JNIEXPORT void JNICALL Java_recipeNo001_HelloWorld_00024NativeWrapper_displayMessageInner 
    (JNIEnv *env, jobject obj) 

它當然有效。

Hello world from enclosing class! 
Hello world from wrapper! 

而就你而言,你還有另外一個問題。如果您沒有在靜態塊中加載庫,那麼在調用native方法之前,您必須確保實例化類中的至少一個對象。

到這裏看看,當涉及到的示例代碼:

https://github.com/mkowsiak/jnicookbook/tree/master/recipeNo034

+0

.oOo。謝謝!與JNI玩得開心! .oOo。 – mko