2

文字列のリストをJavaからJNIを介して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アプローチのいずれかを選択できます。

3番目の解決策の説明:

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

次のコードはを取り、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、配列へのコピーが遅すぎたり、メモリを大量に消費したりするような大規模なものがない限り、私は配列に変換します。

于 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 に答える