[APP]從JNI傳送字串資料送到Java層遭遇\0問題
一般會認為,直接將字串資料直接呼叫到JNI的NewStringUTF, jstring的array中即可, 就像是下面這樣
char* p_str = ""; //你的字串資料
int len = ; //你的字串資料長度
jstring jstr = m_jenv->NewStringUTF(p_str);
return jstr;
但是如果你的字串是中有包含'\0'字元時,就無法這麼做,例如:"abc\0cde\0",因為NewStringUTF是以\0作為結束符號,你得字串長度就會不正確。
所以要傳上述字串回到java層,就需要一套轉換方法,比較簡單的方式是使用jbyte陣列來傳遞,像是下面這樣。
jbyteArray jbarray = m_jenv->NewByteArray(len);
m_jenv->SetByteArrayRegion(jbarray, 0, len, (const jbyte*)p_str);
return jbarray;
JNI回呼的Java方法大概會長這樣
public void OnCallbackTwoString (byte[] b) {
String s;
try {
s = new String(b, "UTF-8"); // or Charset.defaultCharset()
....
} catch (UnsupportedEncodingException e) {
Log.e(TAG, "OnCallbackTwoString:", e);
}
}
在JNI回呼OnCallbackTwoString時使用"([B)Z"
實際上遭遇\0的字元的狀況很多,尤其你的資料是透過native來的從其他sever來的多國語語言文字,都會遭遇這個問題。
另外,如果你是從Java送到JNI層, 建議是用GetStringUTFChars將java的unicode轉換成utf-8, Java官方有描述該轉換必定產生\0結尾的字串。而相關文件顯示java的'\0'傳遞到JNI時會被轉換成'0xc080',所以如果你需要用C的函數parse, 要記得處理這個問題
jstring jstr; // 從Java層來的String
const char *p_utfstr = env->GetStringUTFChars(jstr, 0);
jsize sz = m_jenv->GetStringUTFLength(str);
char* p_str = new p_str[sz+1];
memcpy(p_str, p_utfstr, sz+1);
m_jenv->ReleaseStringUTFChars(jstr, p_utfstr);
return p_str;
留言