2

我需要通过 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() 行崩溃了。这个程序有什么问题?

4

3 回答 3

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);
}
于 2012-10-19T18:06:31.273 回答
0

以下代码将采用 aSet<String>并将其转换为 a 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的复制到数组会太慢或占用太多内存,否则我会转换为数组。

于 2012-10-19T18:02:18.263 回答
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;
}
于 2016-02-18T02:59:54.333 回答