2010-08-03 137 views
3

我想从C++调用的Java方法传回一个字符串。我无法找出应该调用哪个JNI函数来访问该方法,并返回一个jstring值。如何访问在JNI中从C++返回java.lang.String的Java方法的返回值?

我的代码如下:

C++部分

main() { 
    jclass cls; 
    jmethodID mid; 
    jstring rv; 

/** ... omitted code ... */ 

    cls = env->FindClass("ClassifierWrapper"); 
    mid = env->GetMethodID(cls, "getString","()Ljava/lang/String"); 

    rv = env->CallStatic<TYPE>Method(cls, mid, 0); 
    const char *strReturn = env->GetStringUTFChars(env, rv, 0); 

    env->ReleaseStringUTFChars(rv, strReturn); 
} 

Java代码的

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

方法签名(来自 “javap的-s类”)

public java.lang.String getString(); 
    Signature:()Ljava/lang/String; 

回答

8

你应该有

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

然后,你需要调用构造函数来得到一个新的对象:

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

jobject classifierObj = env->NewObject(cls, classifierConstructor); 

你得到的静态方法(即使方法名称是错误的)。但是你需要获取实例方法,因为getString()不是静态的。

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

现在调用方法:

rv = env->CallObjectMethod(classifierObj, getStringMethod, 0); 
const char *strReturn = env->GetStringUTFChars(env, rv, 0); 
+2

类名称应与两端;如:()Ljava/lang/String; – barwnikk 2016-09-04 09:53:02

+0

无法初始化类型为'jstring'(aka'_jstring *') 的类型为'jobject'(aka'_jobject *')的变量 jstring jMacAddr = env-> CallObjectMethod(producDescription, – AdiAtAnd 2016-09-27 03:09:12

+0

just jobject to jstring as如下: rv =(jstring)(env-> CallObjectMethod(classifierObj,getStringMethod,0)); – 2016-12-06 11:47:23

0

第一个问题是ClassifierWrapper.getString()不是静态的。您需要将其设为静态或实例化ClassifierWrapper。

第二个问题是您正在使用GetMethodId而不是GetStaticMethodId。

要调用返回Object(例如String)的方法,您可以调用CallStaticObjectMethod()。这将返回该方法返回的字符串的jobject本地引用。您可以安全地将工作对象转换为jstring(请参阅http://java.sun.com/docs/books/jni/html/types.html),并使用GetStringUTFChars检索字符,并使用GetStringUTFLength获取字符数。

JNI非常棘手。您需要检查所有内容的错误代码(如果没有错误代码,请使用ExceptionCheck())。如果你不检查错误,它会在大多数情况下失败,并且通常不会发生实际错误。

您还需要了解本地引用和全局引用(以及哪些方法会生成新引用)之间的区别,以便不泄漏内存并运行到引用限制。例如,FindClass返回一个对类对象的本地引用,但GetMethodId返回一个MethodID。

好运

0

签名()Ljava/lang/String是错误的,因为一个类名到JVM必须;终止,那么在这种情况下,签名必须是()Ljava/lang/String;

1

的完整的工作解决方案如下:

Ja VA侧

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

机端

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