How do I access return value of a Java method returning java.lang.String from C++ in JNI?

前端 未结 4 1285
没有蜡笔的小新
没有蜡笔的小新 2021-01-12 15:02

I am trying to pass back a string from a Java method called from C++. I am not able to find out what JNI function should I call to access the method and be returned a jstrin

相关标签:
4条回答
  • 2021-01-12 15:23

    The signature ()Ljava/lang/String is wrong, due that a class name into JVM must terminate with ;, then in this case signature must be ()Ljava/lang/String;

    0 讨论(0)
  • 2021-01-12 15:27

    The complete working solution is as below:

    Java Side

    public class ClassifierWrapper {
    public ClassifierWrapper(){}
    public String getString() { return "TEST";}
    }
    

    Native Side

    jclass cls;
    jmethodID mid;
    jstring rv;
    
    
    cls = jniEnv->FindClass("ClassifierWrapper"); //plase also consider your package name as package\name\classname
    
    jmethodID classifierConstructor = jniEnv->GetMethodID(cls,"<init>", "()V");
    if (classifierConstructor == NULL) {
        return NULL; /* exception thrown */
    }
    jobject classifierObj = jniEnv->NewObject( cls, classifierConstructor);
    
    jmethodID getStringMethod = jniEnv->GetMethodID(cls, "getString", "()Ljava/lang/String;");
    
    rv = (jstring)(jniEnv->CallObjectMethod(classifierObj, getStringMethod));
    const char *strReturn = jniEnv->GetStringUTFChars( rv, 0);
    
    
    jniEnv->ReleaseStringUTFChars(rv, strReturn);
    
    0 讨论(0)
  • 2021-01-12 15:37

    The first problem is that ClassifierWrapper.getString() is not static. You will need to make it static or instantiate ClassifierWrapper.

    The second problem is that you are using GetMethodId instead of GetStaticMethodId.

    To invoke a method that returns an Object (such as a String) you would call CallStaticObjectMethod(). That will return a jobject local reference to the String that the method returned. You can safely cast the jobject to a jstring (see http://java.sun.com/docs/books/jni/html/types.html) and use GetStringUTFChars to retrieve the characters and GetStringUTFLength to get the number of characters.

    JNI is very tricky. You need to check the error code for everything (use ExceptionCheck() when there is no error code). If you don't check for errors it will fail silently in most cases and usually not at the point where the actual bug is.

    You also need to understand the difference between local and global references (and what methods generate new references) in order to not leak memory and run into the reference limit. For instance, FindClass returns a local reference to a class object, but GetMethodId returns a MethodID.

    Good luck

    0 讨论(0)
  • 2021-01-12 15:45

    You should have

    cls = env->FindClass("ClassifierWrapper"); 
    

    Then you need to invoke the constructor to get a new object:

    jmethodID classifierConstructor = env->GetMethodID(cls,"<init>", "()V"); 
    if (classifierConstructor == NULL) {
      return NULL; /* exception thrown */
    }
    
    jobject classifierObj = env->NewObject( cls, classifierConstructor);
    

    You are getting static method (even though the method name is wrong). But you need to get the instance method since getString() is not static.

    jmethodID getStringMethod = env->GetMethodID(cls, "getString", "()Ljava/lang/String;"); 
    

    Now invoke the method:

    rv = env->CallObjectMethod(classifierObj, getStringMethod, 0); 
    const char *strReturn = env->GetStringUTFChars(env, rv, 0);
    
    0 讨论(0)
提交回复
热议问题