2012-04-12 47 views
9

我想使用JNI函數來創建一個Java類並使用DeviceId.java構造函數方法設置該類的某些屬性。我能夠使用GetMethodID獲取構造函數方法,但是如何創建Device.java的新實例,然後設置屬性(setId和setCache)。目標是將完全填充的Device.java對象實例返回給調用者。有任何想法嗎?使用JNI來創建,填充和返回一個Java類實例

JNI功能:

JNIEXPORT jobject JNICALL Java_com_test_getID(JNIEnv *env, jclass cls) 
    { 
     jmethodID cnstrctr; 
     jclass c = (*env)->FindClass(env, "com/test/DeviceId"); 
     if (c == 0) { 
      printf("Find Class Failed.\n"); 
     }else{ 
      printf("Found class.\n"); 
     } 

     cnstrctr = (*env)->GetMethodID(env, c, "<init>", "(Ljava/lang/String;[B)V"); 
     if (cnstrctr == 0) { 
      printf("Find method Failed.\n"); 
     }else { 
      printf("Found method.\n"); 
     } 

     return (*env)->NewObject(env, c, cnstrctr); 
    } 

的Java類:

package com.test; 

public class DeviceId { 
    private String id; 
    private byte[] cache; 

     public DeviceId(){} 
    public DeviceId(String id, byte[] cache){ 
     this.id=id; 
     this.cache=cache; 
    } 

    public byte[] getCache() { 
     return cache; 
    } 

    public void setCache(byte[] cache) { 
     this.cache = cache; 
    } 

    public String getId() { 
     return id; 
    } 

    public void setId(String id) { 
     this.id = id; 
    } 
} 
+0

什麼是''[''中的[B''(Ljava/lang/String; [B] V「'? – 2016-08-30 18:48:19

+0

@WilburWhateley,它是[字節數組](http://stackoverflow.com/a/30815321/4440694) – 2016-10-14 02:08:20

回答

7

當你叫GetMethodID,你們兩個參數的構造函數提供的簽名。因此,你只需要通過你的jstring和當你調用NewObjectjbytearray - 例如:

return (*env)->NewObject(env, c, cnstrctr, id, cache); 

你不需要,除非你決定調用0參數的構造函數調用setIdsetCache方法 - 這會讓你的代碼複雜化,因爲你必須給這些人打電話GetMethodID並給他們打電話。更簡單的繼續沿着你所在的路線走。

+2

應該有NewGlobalRef,因爲當我們返回時它會超出範圍。 – ssk 2014-02-04 22:43:36

0

我想返回自定義來自的Java對象返回到Java的JNI的cpp代碼。解決方法是從cpp函數返回jobject,並在本機方法聲明中使用我們的自定義Java對象。

public class PyError { 

    public String message; 

    public boolean occurred; 

    public PyError(boolean occurred, String message){ 
     this.message = message; 
     this.occurred = occurred; 
    } 
} 

和方法聲明中的Java:

native PyError nativePythonErrorOccurred(); 

的CPP面:

extern "C" JNIEXPORT jobject JNICALL 
Java_com_your_package_nativePythonErrorOccurred(JNIEnv *env, jobject obj) { 

    jclass javaLocalClass = env->FindClass("com/your/package/PyError"); 

    if (javaLocalClass == NULL) { 
     LOGP("Find Class Failed.\n"); 
    } else { 
     LOGP("Found class.\n"); 
    } 

    jclass javaGlobalClass = reinterpret_cast<jclass>(env->NewGlobalRef(javaLocalClass)); 

    // info: last argument is Java method signature 
    jmethodID javaConstructor = env->GetMethodID(javaGlobalClass, "<init>", "(ZLjava/lang/String;)V"); 

    if (javaConstructor == NULL) { 
     LOGP("Find method Failed.\n"); 
    } else { 
     LOGP("Found method.\n"); 
    } 

    jobject pyErrorObject = env->NewObject(javaGlobalClass, javaConstructor, true, env->NewStringUTF("Sample error body")); 
    return pyErrorObject; 
} 

確定方法的使用 javap -s java.your.package.YourClass簽名。 另外,看看here

如果遇到類似的錯誤:JNI ERROR (app bug): attempt to use stale Global 0xf2ac01ba你的方法簽名是錯誤的,你傳遞錯誤的參數env->NewObject()或你不使用JNI對象的全局狀態 - 更多here