2012-04-12 21 views
9

Próbuję użyć funkcji JNI, aby utworzyć klasę Java i ustawić niektóre właściwości tej klasy, używając metody konstruktora DeviceId.java. Jestem w stanie uzyskać metodę konstruktora za pomocą metody GetMethodID, ale w jaki sposób utworzyć nową instancję Device.java, a następnie ustawić właściwości (setId i setCache). Celem jest zwrócenie całkowicie zapełnionej instancji Device.java Object do osoby dzwoniącej. Jakieś pomysły?Użyj JNI, aby utworzyć, wypełnić i zwrócić instancję klasy Java

JNI Funkcja:

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 Class:

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

Co to jest "" [B "' w '" (Ljava/lang/String; [B) V "'? –

+0

@WilburWhateley, to [tablica bajtów] (http://stackoverflow.com/a/30815321/4440694) –

Odpowiedz

7

Kiedy zadzwoniłeś GetMethodID, to pod warunkiem, że podpis na dwa-Arg konstruktora. Tak więc, po prostu trzeba zdać jstring i jbytearray kiedy zadzwonić NewObject - na przykład:

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

Nie trzeba zadzwonić metody setId i setCache chyba że użytkownik zdecyduje się zadzwonić do 0-Arg konstruktora - i to tylko komplikuje twój kod, ponieważ będziesz musiał zadzwonić pod numer GetMethodID i zadzwonić do nich. Prostsze kontynuowanie trasy, na której się znajdujesz.

+2

Powinien istnieć obiekt NewGlobalRef, ponieważ po powrocie wykracza poza zakres. – ssk

0

Chciałem zwrócić niestandardowego obiektu Java z JNI w kodzie cpp z powrotem do Javy. Rozwiązaniem jest zwrócenie jobject z funkcji cpp i użycie naszego niestandardowego obiektu Java w deklaracji metody natywnej.

public class PyError { 

    public String message; 

    public boolean occurred; 

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

i sposób deklaracja w Javie:

native PyError nativePythonErrorOccurred(); 

na stronie 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; 
} 

Ustal podpis metody wykorzystującej javap -s java.your.package.YourClass. Zobacz także here.

Jeśli wystąpi błąd podobny do: JNI ERROR (app bug): attempt to use stale Global 0xf2ac01ba podpis metoda jest źle, jesteś przejazdem niewłaściwych argumentów env->NewObject() lub nie używasz stan globalnej JNI obiektów - więcej here.

Powiązane problemy