将字符串列表从Java传递到C.

时间:2012-10-16 04:48:26

标签: java c eclipse list java-native-interface

我需要通过JNI将字符串列表从Java传递给C. 我的Java程序传递一个List参数,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()行崩溃了。 这个程序有什么问题?

3 个答案:

答案 0 :(得分: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);
}

答案 1 :(得分:0)

以下代码将使用Set<String>并将其转换为std::vector<std::string>,但我不会这样做,您最好使用{{1将集合转换为数组在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); } } 复制到数组太慢或占用太多内存,否则我会转换为数组。

答案 2 :(得分: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;
}