2010-08-03 77 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);