原贴http://topic.csdn.net/u/20101022/16/1b2e0cec-b9d2-42ea-8d9c-4f1bb8320a54.html?r=70149216 ,看过并动手实现,记录下来以备再用。
如果是在java层,有String类可以很好的转换各种编码,在ndk下面就没有现成的公开的工具,不过可以用icu4c。
ICU4C 是IBM的国际化开发组件ICU的C语言实现版本。在android系统里也有实现。ndk里面并没有公开可用的api,需要自己加载动态库来调用转换函数。
android下icu库路径为"/system/lib/libicuuc.so",主要用到的转换函数为ucnv_convert_?_?。这里的问号是根据版本的不同函数名也不一样。在2.2的模拟器中的libicuuc.so中此函数名为ucnv_convert_4_2,在2.1模拟器中为 ucnv_convert_3_8,貌似要根据版本不同来分开对待,还没发现可以统一的办法。
函数原型:
void ucnv_convert(const char *, const char *, char * , int32_t , const char *, int32_t,int32_t*);
用法:
//声明函数指针
void (*ucnv_convert)(const char *, const char *, char * , int32_t , const char *, int32_t,int32_t*)=0;
//加载动态库
void* pDL = dlopen("/system/lib/libicuuc.so", RTLD_LAZY);
//这里以android2.2为例,函数名就是ucnv_convert_4_2
ucnv_convert = (void (*)(const char *, const char *, char * , int32_t , const char *, int32_t,int32_t*))dlsym(pDL, "ucnv_convert_4_2");
//加载成功就可以用了
if(ucnv_convert){
char* cbuf = "...";
char buffer[100];
int errcode = 0;
//utf8是目标编码,ucs2是原字符编码
//buffer是存放转换出来的字符的缓冲,给了100字节
//cbuf是要转换的字符串指针
//errcode是错误编码,具体可网上搜索
ucnv_convert("utf8","ucs2", buffer, 100, cbuf, strlen(cbuf),&errcode);
}
转换成功后的字符串就放在buffer里面,如果出错了就会在errcode里面放错误代码。
如标题所示,ndk下还有一个宽字符,也就是wchar_t的问题,跟其他平台移植也是个麻烦的事。
linux下wchar_t默认是4个字节,而windows下(包括CE,MOBILE)和symbian下都是2个字节。解决的办法是在 android.mk文件中,找到LOCAL_CFLAGS 为其加上编译开关 -fshort-wchar(如果没有此项就手动写上),如 LOCAL_CFLAGS := -fshort-wchar 。这样强制编译器用2个字节处理wchar_t,不过编译时会有warning,可以不管。
这样虽然编译器处理成2个字节,但是预编译的库libc等依然是4个字节,会导致wcslen等函数无法使用(其实ndk下wcslen本来就是废的),解决的办法可以重新编译libc,不过最简单的还是自己实现wcslen就行了。
下面的代码是copy网上的,具体哪里的忘了,可以把wchar_t转换成char字符串,这样就可以用icu库随意转换了。
//取得wchar_t字符串长度
int wlen(const wchar_t* strString){
int i=0;
while (1) {
if (strString[i] == 0) {
break;
}else{
i++;
}
}
return i;
}
char *W2C(const wchar_t *pw , char *pc)
{
*pc++ = *pw >> 8 ;
*pc = *pw ;
return 0 ;
}
//转换字符串
char *wstr2cstr(const wchar_t *pwstr, char *pcstr, size_t len) {
char *ptemp = pcstr;
if (pwstr != NULL && pcstr != NULL) {
size_t wstr_len = wlen(pwstr);
len = (len > wstr_len) ? wstr_len : len;
while (len-- > 0) {
W2C(pwstr, pcstr);
pwstr++;
pcstr += 2;
}
*pcstr = '/0';
return ptemp;
}
return 0;
}
使用wstr2cstr就可以转换出来。这里还有个字节序的问题,在W2C函数里面,一个wchar_t转到char究竟是低位在前还是高位在前恐怕还是要看转换前后的编码具体对待。
分享到:
相关推荐
Android NDK使用Iconv进行编码转换,可以在Unicode、GBK、UTF-8之前互转
在Android NDK中还没有现成的函数来处理字符串的相互转换,但是Android底层有个libicuuc.so库文件,在目录/system/lib/下可以找到这个文件。在这个文件中有个函数ucnv_convert,我们可以从这个库中找到这个函数,...
使用Android NDK编译Android平台的eXosip库,有静态库和动态库。
Android ndk下获取系统使用时间
Android NDK 安装以及 HelloWorld!测试
android ndk 使用方法android ndk 使用方法
NDK提供了一系列的工具,帮助开发者快速开发C(或C++)的动态库,并能自动将so和java应用一起打包成apk,并集成了交叉编译器,并提供了相应的mk文件隔离CPU、平台、ABI等差异,开发人员只需要简单修改mk文件
文档里描述了移植libiconv方法,并附有源码,经过验证ok
这个虽然只是个简单的jnidemo、但是涵盖了Android.mk 和Application.mk 的原理 重点是Android NDK编译的理解 mac 系统下 切换到jni目录,然后呢个 ndk-build
curl库源码添加了curl_config.h和mk文件,可以直接跳转到目录使用ndk-build编译出so库.
Android NDK 开发时需要的 常用的JNI API
android ndk详细介绍
博客名称 : 【Android NDK 开发】在 C 代码中获取 Android 系统信息 ( NDK 项目创建 | NDK 配置 | 获取 Android 系统版本号 ) 博客地址 : https://hanshuliang.blog.csdn.net/article/details/102933704
Android中通过NDK使用OpenCV库.pdf
windows下androidNDK环境配置
详细的描述了Android NDK下编译ffmpeg开源库的步骤。
ndk网盘下载,方便不能科学上网的同学下载。包含Windows和Mac版本。版本号r14-r20,全部下载搬运自谷歌Android官网。下载后是一个文本文件,用文本编辑器打开即可看到网盘下载地址。
下载 https://developer.android.google.cn/ndk/downloads/ https://developer.android.google.cn/ndk/downloads/older_releases 编译ffmpeg:最高版本16b,再高的版本...export NDK=/home/quantum6/android-ndk-16b
android-ndk(android-ndk-r25b-linux.zip)适用于Linux系统
android-ndk(android-ndk-r26b-windows.zip)适用于Windows系统