java的jni 为Java和c/c++语言间的通信提供了统一的接口。在两种语言的字符串转换方面,我搜了搜,发现很多都是人云亦云。如果不是因为做项目遇到遗留的bug,恐怕我也人云亦云了。

先看一下 jchar的定义

typedef unsigned short  jchar;          /* unsigned 16 bits */

 是一个无符号端整型,而不是wchar_t。(参考jni.h,这文件在Android NDK里面,搜索就能找到)

为了兼容早期的jvm ,java使用16比特(两字节)表示一个小于65535的UNICODE码,用代理对的形式表示其他UNICODE码(关于代理对,http://zh.wikipedia.org/zh-cn/UTF-16

而将UNICODE编码时,若使用变种UTF8,java会把字节 00  变为 0xC0 80,编码代理对更复杂(http://zh.wikipedia.org/wiki/UTF-8)。

好了,有了以上的认识,在使用JNI的一些接口时就要注意了

 

jstring  到 c/c++字符串

应从 jchar 到 wchar_t  的转换,而不是jchar  到 char。也就是在转换时,要保持jstring的每个jchar的值不变。

JNIEnv *env = 获取相关句柄;
jstring jstr = java字符串;

//获取java字符串的长度
jsize jstr_len = env->GetStringLength(jstr);
//获取java字符串的jchar指针
const jchar * pjstr = env->GetStringChars(jstr);

//申请c字符串的内存空间
wchar_t *pcstr = new wchar_t[jstr_len];//通常 sizeof(wchar_t)不小于2,若为1,应考虑使用其他类型来容纳jchar
//或者
std::wstring wstr;
wstr.assign(jstr_len,0);

//复制
jstr_len --;
while( jstr_len > -1 )
{
    pcstr[jstr_len ] = pjstr[jstr_len];
    //或者
     wstr[jstr_len] = pjstr[jstr_len];
    jstr_len -- ;
}

上面代码使用了GetStringChars而不是GetStringUTFChars。之所以这样做,就是为了保持java字符串到c/c++字符串的无损转换。

不过,仍然要注意一个问题,就00字节的处理,建议使用c++的wstring类。

 

如果:

        1、jstring的每一个jchar都在[1,127]内

        2、或者,你需要做UTF8转换但是不关心GetStringUTFChars采用变种UTF8还是标准UTF8,也不关心可逆转换

可以使用GetStringUTFChars。

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐