2017-05-10 2 views
-3

왜 jni 측에서 한 번 오류가 발생하고 Java 측에서 한 번 더 오류가 발생합니까? for 루프없이 배열 만 반환 할 수 있습니까? JNI를 통해 자바 문자열 []를 반환하기 위해jni c/C++ 11에서 문자열 배열을 반환하고 C++ 측에서 for 루프없이 java에서 사용 하시겠습니까?

JNIEXPORT jobjectArray JNICALL Java_main_returndays(JNIEnv *env, jobject jobj) 
{ 

    char *days[]={"Sunday", 
       "Monday", 
       "Tuesday", 
       "Wednesday", 
       "Thursday", 
       "Friday", 
       "Saturday"}; 

    jstring str; 
    jobjectArray day = 0; 
    jsize len = 7; 
    int i; 

    day = (*env)->NewObjectArray(env,len,(*env)->FindClass(env,"java/lang/String"),0); 

    for(i=0;i<7;i++)//// without this loop ? 
    { 
    str = (*env)->NewStringUTF(env,days[i]); 
    (*env)->SetObjectArrayElement(env,day,i,str); 
    } 

return day; 
} 
+0

'while while'을 사용해 보셨습니까? – user2079303

+0

for 루프 또는 while 루프는 동일한 것이고 다른 조건은 –

답변

1

, 당신은 배열을 만든 다음 변환하고 배열에 각 문자열을 설정해야합니다. char **를 Java에 다시 전달하는 것과 같은 지름길은 없습니다.

그러나 ... 당신의 목표가 JNI를 통해 C++에서 자바 문자열을 생성하는 것을 피하고 대신 자바로 처리한다면이 작업을 수행 할 수 있습니다. 때때로 그럴만한 이유가 있습니다. 우리의 소프트웨어에서는 C++에서 Java로 복잡한 데이터 구조를 전달합니다. 우리는 JNI를 사용하여 데이터 구조를 구축하는 것이 매우 느리다는 것을 발견했습니다 (JNI 메소드 호출은 각각 1000 클럭 사이클과 비슷합니다). C++에서 바이트 배열로 직렬화하고, 단일 JNI 바이트 배열을 만들고, JNI 경계에서 Java로 넘겨주고, Java에서 바이트 배열을 deserialize하는 것이 더 빠릅니다.

완전한 예제를 제공하지는 않겠지 만, 다음과 같이됩니다. C++에서 각 문자열 사이에 nulls가있는 바이트 배열을 작성한 다음 Java에서 처리하도록 List (String [])보다 손쉽게 처리 할 것입니다.

C++ :

// Find overall length with nulls 
int len = 0; 
for (int i = 0; i < sizeof(days)/sizeof(char*); i++) { 
    len += strlen(days[i]) + 1; 
} 
// Fill C++ byte array 
char* cBytes = new char[len]; 
char* ptr = cBytes; 
for (int i = 0; i < sizeof(days)/sizeof(char*); i++) { 
    strcpy(ptr, days[i]); 
    ptr += strlen(days[i]) + 1; 
} 
// Copy C++ to Java 
jbyteArray jBytes = env->NewByteArray(len); 
env->SetByteArrayRegion(jBytes, 0, len, cBytes); 
delete [] cBytes; 
return jBytes; 

자바 :

byte jBytes[] = // call C++ via JNI 
List<String> strs = new ArrayList<>(); 
int offset = 0; 
// break byte array at null, convert to String 
while (offset < jBytes.length) { 
    for (int i = offset; true; i++) { 
     if (jBytes[i] == 0) { 
     // Default code page assumed. You could also pass a Charset. 
     strs.add(new String(jBytes, offset, i - offset)); 
     offset = i + 1; 
     break; 
     } 
    } 
} 

나는 보통 NativeByteBuffer 래퍼의 어떤 종류를 포함, C 사이에 배열을 전달 ++ 및 Java의 "더 최적"방법이 있다는 것을 알고 있습니다. 그러나 이러한 방법은 종종 특별한 경우를 가지며 더 복잡합니다.

+0

입니다. 노력과 아이디어가 필요합니다. –

관련 문제