How to pass a C String Emoji to Java via JNI

非 Y 不嫁゛ 提交于 2020-04-30 11:10:50

问题


I am trying to pass a database value to Java via JNI :

__android_log_print(ANDROID_LOG_ERROR, "MyApp", "c_string >>> %s", cStringValue);

prints : c_string >>> 👑👟👓

env->SetObjectField(jPosRec, myJniPosRec->_myJavaStringValue, env->NewStringUTF(strdup(cStringValue)));  

However, this fails without errors.

How can you go about passing special characters (such as emojis) to Java in JNI?

Thank you all in advance.


回答1:


Cribbing from my answer here, you can use the JNI equivalent of

Charset.forName("UTF-8").decode(bb).toString()

as follows, where each paragraph roughly implements one step, and the last sets your object field to the result:

jobject bb = env->NewDirectByteBuffer((void *) cStringValue, strlen(cStringValue));

jclass cls_Charset = env->FindClass("java/nio/charset/Charset");
jmethodID mid_Charset_forName = env->GetStaticMethodID(cls_Charset, "forName", "(Ljava/lang/String;)Ljava/nio/charset/Charset;");
jobject charset = env->CallStaticObjectMethod(cls_Charset, mid_Charset_forName, env->NewStringUTF("UTF-8"));

jmethodID mid_Charset_decode = env->GetMethodID(cls_Charset, "decode", "(Ljava/nio/ByteBuffer;)Ljava/nio/CharBuffer;");
jobject cb = env->CallObjectMethod(charset, mid_Charset_decode, bb);

jclass cls_CharBuffer = env->FindClass("java/nio/CharBuffer");
jmethodID mid_CharBuffer_toString = env->GetMethodID(cls_CharBuffer, "toString", "()Ljava/lang/String;");
jstring str = env->CallObjectMethod(cb, mid_CharBuffer_toString);

env->SetObjectField(jPosRec, myJniPosRec->_myJavaStringValue, str);  



回答2:


First off, you are leaking the memory allocated by strdup(). You need to pass the char* pointer from strdup() to free() when you are done using it. However, there is no need to call strdup() in this situation at all, you can pass cStringValue directly to JNI's NewStringUTF() function.

That said, JNI's NewStringUTF() function requires the input C string to be in "modified" UTF-8 format, which standard C++ knows nothing about. While it is possible to create a C string in that format, you will have to do so manually. Since Java strings use a UTF-16 interface, and standard C++ has facilities to work with UTF-16 strings, I strongly suggest you use JNI's NewString() function instead.

If your database code allows you to retrieve strings in UTF-16 format, then you are all set. If not, you will have to convert the strings to UTF-16 before passing them to NewString() (just as you would have to convert them to "modified" UTF-8 if you continue using NewStringUTF()).



来源:https://stackoverflow.com/questions/59998653/how-to-pass-a-c-string-emoji-to-java-via-jni

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!