Use JNI to Create, Populate and Return a Java Class Instance

后端 未结 2 521
南笙
南笙 2020-12-14 11:24

I\'m trying to use a JNI function to create a Java class and set some properties of that class using the DeviceId.java constructor method. I\'m able to get the constructor

相关标签:
2条回答
  • 2020-12-14 12:02

    When you called GetMethodID, you provided the signature for the two-arg constructor. Thus, you just need to pass your jstring and a jbytearray when you call NewObject - for example:

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

    You don't need to call the setId and setCache methods unless you decide to call the 0-arg constructor - and that just complicates your code since you'll have to call GetMethodID for those and call them. Simpler to continue down the route you're on.

    0 讨论(0)
  • 2020-12-14 12:02

    I wanted to return a custom Java object from JNI's cpp code back to Java. The solution is to return a jobject from cpp function and use our custom Java object in native method declaration.

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

    and method declaration in Java:

    native PyError nativePythonErrorOccurred();
    

    on the cpp side:

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

    Determine the signature of the method using javap -s java.your.package.YourClass. Also, have a look here.

    If you encounter error similar to: JNI ERROR (app bug): attempt to use stale Global 0xf2ac01ba your method signature is wrong, you're passing wrong arguments to env->NewObject() or you're not using global state of jni objects - more here.

    0 讨论(0)
提交回复
热议问题