2012-10-16 38 views
2

我需要通過JNI將字符串列表從Java傳遞到C. 我的Java程序傳遞一個List參數,C程序接受一個列表。將字符串列表從Java傳遞到C

下面是我試過的代碼。

JNIEXPORT jobject JNICALL Java_jni_CallJNIfunction(JNIEnv *env, 
                 jobjectArray jParameters){ 

    list<const char*> cParameters; 

    jsize stringCount = env->GetArrayLength(jParameters); 

    for (int i=0; i<stringCount; i++) { 
     jstring arrElement = (jstring) (env->GetObjectArrayElement(jParameters, i)); 
     const char* nativeElement = env->GetStringUTFChars(arrElement, NULL); 

     cParameters.push_back(nativeElement); 
     env->ReleaseStringUTFChars(arrElement, nativeElement); 
    } 

    CallCfunction(cParameters); 

} 

但是我的JVM在GetStringUTFChars()行崩潰。 這個程序有什麼問題?

+1

當你說你傳遞的參數的'List',你真的意味着一個數組? C函數似乎被寫爲接受一個數組,如果Java傳遞一個'List'對象,你可以期望它在某個時刻崩潰。 – Joni

回答

2

你這樣做:

const char* nativeElement = env->GetStringUTFChars(arrElement, NULL); 
cParameters.push_back(nativeElement); 
env->ReleaseStringUTFChars(arrElement, nativeElement); 

您鬆開存儲到列表中的字符串,所以你的列表中包含了很多不好的指針!

您必須將字符串複製到長時間分配的空間中,您可以在std :: string,char * + malloc或use-it-and-forget-it方法之間進行選擇。

解釋第三個解決方案:

for(int i = 0; i < stringCount; ++i) 
{ 
    jstring arrElement = (jstring) (env->GetObjectArrayElement(jParameters, i)); 
    const char* nativeElement = env->GetStringUTFChars(arrElement, NULL); 
    CallCfunction(nativeElement); // modified to process an item not a list< 
    env->ReleaseStringUTFChars(arrElement, nativeElement); 
} 
0

下面的代碼將採取Set<String>並將其轉換成一個std::vector<std::string>,但我不這樣做,你會更好的轉換集使用toArray方法上Set一個數組,然後你可以使用你的原始代碼。

JNIEXPORT jobject JNICALL Java_jni_CallJNIfunction(
    JNIEnv *env, 
    jclass, 
    jobject setObj) { 

    jmethodID iteratorID = env->GetMethodID(env->FindClass("java/util/Set"), "iterator", "()Ljava/util/Iterator;"); 
    jclass iterator = env->FindClass("java/util/Iterator"); 
    jmethodID hasNextID = env->GetMethodID(iterator, "hasNext", "()Z"); 
    jmethodID nextID = env->GetMethodID(iterator, "next", "()Ljava/lang/Object;"); 

    std::vector<std::string> strSet; 

    jobject iteratorObj = env->CallObjectMethod(setObj, iteratorID); 
    while (env->CallBooleanMethod(iteratorObj, hasNextID) == JNI_TRUE) { 
     jstring current = (jstring)env->CallObjectMethod(iteratorObj, nextID); 
     const char* str = env->GetStringUTFChars(current, NULL); 

     strSet.push_back(str); 

     env->ReleaseStringUTFChars(current, str); 
    } 
} 

但是,除非你有一個巨大的Set其複製到一個數組是過慢或佔用太多的內存,那麼我會轉換成數組。

0

在樸素簡單C函數的第一個答案是:

char **GetStringsfromJniStringArray(JNIEnv *env, jobjectArray stringArray) { 
    size_t stringCount = (size_t)(*env)->GetArrayLength(env, stringArray); 
    char **Strings=calloc(stringCount, sizeof(char*)); 
    int i = 0; 
    for(i = 0; i < (int)stringCount; ++i) 
    { 
     jstring jniString = (jstring) (*env)->GetObjectArrayElement(env, stringArray, i); 
     const char *TempString = (*env)->GetStringUTFChars(env, jniString, NULL); 
     Strings[i] = calloc(strlen(TempString)+1, sizeof(char)); 
     strcpy(Strings[i], TempString); 
     (*env)->ReleaseStringUTFChars(env, jniString, TempString); 
    } 
    return Strings; 
}