2012-10-16 7 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

정말 당신을 배열이란 뜻이야? 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>로 변환,하지만이 작업을 수행 할 것입니다, 당신은 SettoArray 방법을 사용하여 배열에 세트를 변환 더 나을 것, 당신은 사용할 수 있습니다 원래 코드. 당신이 너무 느리게 또는 너무 많은 메모리를 취할 것 배열에 복사 대규모 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); 
    } 
} 

하지만, 그때는 배열로 변환합니다.

0

일반 간단한 C 함수의 첫 번째 대답은 :

당신이, 당신이 인수`List` 통과 말할
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; 
} 
관련 문제