关于cocos2dx中文转UTF8码的解决方案

文章转载请注明出处:作者帘卷西风的专栏(http://blog.csdn.net/ljxfblog)

cocos2dx支持中文显示,只要将中文字符转换成UTF-8字符集就可以正常显示,不过在实践上还是会出现很多问题会困扰开发者。

通常来说,目前的解决方案有以下几种:

1、把代码文件(.h/.cpp/.lua等)的文件编码格式改成UTF-8格式即可,这对于单机游戏来说是很好的解决方案。但是对于服务器传过来的文字则无能为力。

2、使用iconv库来做转换,使用接口比较简单,win32版本也能直接用上,但是在安卓上面就需要自己编译整合iconv的源码,没做过的有一些难度。

3、自立更生,自己写代码来实现。

   本文主要讲第三种方案,第二种方案其实也不错,但是更折腾一点,以后有时间在来折腾。

  自己写转utf-8的接口,主要需要考虑以下几个问题。主要都是跨平台的问题。

1、在win32下面,很简单也很容易实现,因为win32API已经帮我们提供了相关的接口(WideCharToMultiByte /MultiByteToWideChar等),只需要稍微处理一下即可。相关代码如下:

[cpp]  view plain copy
  1. const char* gb23122utf8(const char* gb2312)        
  2. {      
  3.     int len = MultiByteToWideChar(0, 0, gb2312, -1, NULL, 0);        
  4.     wchar_t* wstr = new wchar_t[len+1];        
  5.     memset(wstr, 0, len+1);        
  6.     MultiByteToWideChar(0, 0, gb2312, -1, wstr, len);        
  7.     len = WideCharToMultiByte(65001, 0, wstr, -1, NULL, 0, NULL, NULL);        
  8.     char* str = new char[len+1];    
  9.     memset(str, 0, len+1);        
  10.     WideCharToMultiByte(65001, 0, wstr, -1, str, len, NULL, NULL);        
  11.     if(wstr) delete[] wstr;        
  12.     return str;    
  13. }      

2、在安卓平台,就稍微麻烦一点。首先考虑的是,c语言有和win32接口相似的接口(mbstowcs/wcstombs等),按这种方案,需要使用setlocale这个接口,经过测试发现,这个接口在windows和linux都有效,能正确转成utf-8码,但是在安卓上这个接口无效,始终返回NULL,所以不能使用mbstowcs/wcstombs。 后来辗转查了一些资料,决定使用icu库,这个库在大部分安卓机器上都有,只是版本不一样,但是还是能够正确转,姑且暂时使用这种苟且的方案吧,以后再使用高大上的方案。具体代码如下:

  首先是需要找到icu库中的接口函数地址:

[cpp]  view plain copy
  1. #include <dlfcn.h>    
  2. void (*ucnv_convert)(const char *, const char *, char * , int32_t , const char *, int32_t,int32_t*) = 0;    
  3. bool openIcuuc()    
  4. {    
  5.     void* libFile = dlopen("/system/lib/libicuuc.so", RTLD_LAZY);     
  6.     if (libFile)    
  7.     {    
  8.         ucnv_convert = (void (*)(const char *, const char *, char * , int32_t , const char *, int32_t,int32_t*))dlsym(libFile, "ucnv_convert_3_8");    
  9.     
  10.         int index = 0;    
  11.         char fun_name[64];    
  12.         while (ucnv_convert == NULL)    
  13.         {    
  14.             sprintf(fun_name, "ucnv_convert_4%d", index++);    
  15.             ucnv_convert = (void (*)(const char *, const char *, char * , int32_t , const char *, int32_t,int32_t*))dlsym(libFile, fun_name);    
  16.             if (ucnv_convert)     
  17.                 return true;                    
  18.             if (++index > 11)     
  19.                 break;    
  20.         }    
  21.         dlclose(libFile);    
  22.     }    
  23.     return false;    
  24. }     

其次,就是转换函数代码如下:

[cpp]  view plain copy
  1. const char* gb23122utf8(const char * gb2312)    
  2. {    
  3.     if (ucnv_convert == NULL)    
  4.     {    
  5.         openIcuuc();    
  6.     }           
  7.     if (ucnv_convert)    
  8.     {    
  9.         int err_code = 0;    
  10.         int len = strlen(gb2312);    
  11.         char* str = new char[len * 2 + 10];        
  12.         memset(str, 0, len * 2 + 10);    
  13.         ucnv_convert("utf-8""gb2312", str, len * 2 + 10, gb2312, len, &err_code);    
  14.         if (err_code == 0)    
  15.         {    
  16.             return str;    
  17.         }    
  18.     }    
  19.     char test[256] = "gb23122utf8 error";    
  20.     char* str = new char[30];     
  21.     strcpy(str, test);    
  22.     return str;    
  23. }    
好了,这就大功告成了,在几台安卓机上测试都OK,但是在模拟器上失败,可能是缺少库的问题。

当然如果有需要可以把这个接口暴露给lua使用。

[cpp]  view plain copy
  1. static int luaA_Strg2u(lua_State *L)    
  2. {    
  3.     const char* gb2312 = luaL_checkstring(L, 1);    
  4.     const char* utf8 = gb23122utf8(gb2312);    
  5.     lua_pushstring(L, utf8);    
  6.     delete [] utf8;    
  7.     return 1;    
  8. }    
  9.     
  10. void registerLuaFunction(lua_State* luaState)    
  11. {    
  12.     lua_register(luaState, "strg2u", luaA_Strg2u);      
  13.     tolua_api4lua_open(luaState);    
  14. }    

最后把我封装的文件分享给大家吧!
文件名:GB23122Utf8.h

[cpp]  view plain copy
  1. #ifndef __GB23122Utf8_H_  
  2. #define __GB23122Utf8_H_  
  3.   
  4. #if (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32)  
  5.     const char* gb23122utf8(const char* gb2312)      
  6.     {    
  7.         int len = MultiByteToWideChar(0, 0, gb2312, -1, NULL, 0);      
  8.         wchar_t* wstr = new wchar_t[len+1];      
  9.         memset(wstr, 0, len+1);      
  10.         MultiByteToWideChar(0, 0, gb2312, -1, wstr, len);      
  11.         len = WideCharToMultiByte(65001, 0, wstr, -1, NULL, 0, NULL, NULL);      
  12.         char* str = new char[len+1];  
  13.         memset(str, 0, len+1);      
  14.         WideCharToMultiByte(65001, 0, wstr, -1, str, len, NULL, NULL);      
  15.         if(wstr) delete[] wstr;      
  16.         return str;  
  17.     }    
  18. #endif  
  19. #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)  
  20. #include <dlfcn.h>  
  21.   
  22.     void (*ucnv_convert)(const char *, const char *, char * , int32_t , const char *, int32_t,int32_t*) = 0;  
  23.   
  24.     bool openIcuuc()  
  25.     {  
  26.         void* libFile = dlopen("/system/lib/libicuuc.so", RTLD_LAZY);   
  27.         if (libFile)  
  28.         {  
  29.             ucnv_convert = (void (*)(const char *, const char *, char * , int32_t , const char *, int32_t,int32_t*))dlsym(libFile, "ucnv_convert_3_8");  
  30.   
  31.             int index = 0;  
  32.             char fun_name[64];  
  33.             while (ucnv_convert == NULL)  
  34.             {  
  35.                 sprintf(fun_name, "ucnv_convert_4%d", index++);  
  36.                 ucnv_convert = (void (*)(const char *, const char *, char * , int32_t , const char *, int32_t,int32_t*))dlsym(libFile, fun_name);  
  37.                 if (ucnv_convert)   
  38.                     return true;                  
  39.                 if (++index > 11)   
  40.                     break;  
  41.             }  
  42.             dlclose(libFile);  
  43.         }  
  44.         return false;  
  45.     }   
  46.     const char* gb23122utf8(const char * gb2312)  
  47.     {  
  48.         if (ucnv_convert == NULL)  
  49.         {  
  50.             openIcuuc();  
  51.         }         
  52.         if (ucnv_convert)  
  53.         {  
  54.             int err_code = 0;  
  55.             int len = strlen(gb2312);  
  56.             char* str = new char[len * 2 + 10];      
  57.             memset(str, 0, len * 2 + 10);  
  58.             ucnv_convert("utf-8""gb2312", str, len * 2 + 10, gb2312, len, &err_code);  
  59.             if (err_code == 0)  
  60.             {  
  61.                 return str;  
  62.             }  
  63.         }  
  64.         char test[256] = "gb23122utf8 error";  
  65.         char* str = new char[30];   
  66.         strcpy(str, test);  
  67.         return str;  
  68.     }  
  69. #endif  
  70. #if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)  
  71.     const char* gb23122utf8(const char * gb2312)  
  72.     {  
  73.         return gb2312;   
  74.     }  
  75. #endif  
  76.   
  77. #endif //__GB23122Utf8_H_  
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值