Android JNI 由GetStringUTFChars引起的问题

本文详细阐述了Java与C/C++间的通信接口JNI,特别聚焦于字符串转换过程中的关键细节,包括jchar类型与wchar_t的区别、UNICODE编码原理、代理对形式以及UTF-8编码的复杂性。通过实例代码展示了如何正确地进行jstring到c/c++字符串的无损转换,并特别强调了处理00字节的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值