關於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等),只需要稍微處理一下即可。相關代碼如下:

const char* gb23122utf8(const char* gb2312)    
{  
	int len = MultiByteToWideChar(0, 0, gb2312, -1, NULL, 0);    
	wchar_t* wstr = new wchar_t[len+1];    
	memset(wstr, 0, len+1);    
	MultiByteToWideChar(0, 0, gb2312, -1, wstr, len);    
	len = WideCharToMultiByte(65001, 0, wstr, -1, NULL, 0, NULL, NULL);    
	char* str = new char[len+1];
	memset(str, 0, len+1);    
	WideCharToMultiByte(65001, 0, wstr, -1, str, len, NULL, NULL);    
	if(wstr) delete[] wstr;    
	return str;
}  
2、在安卓平臺,就稍微麻煩一點。首先考慮的是,c語言有和win32接口相似的接口(mbstowcs/wcstombs等),按這種方案,需要使用setlocale這個接口,經過測試發現,這個接口在windows和linux都有效,能正確轉成utf-8碼,但是在安卓上這個接口無效,始終返回NULL,所以不能使用mbstowcs/wcstombs。後來輾轉查了一些資料,決定使用icu庫,這個庫在大部分安卓機器上都有,只是版本不一樣,但是還是能夠正確轉,姑且暫時使用這種苟且的方案吧,以後再使用高大上的方案。具體代碼如下:

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

#include <dlfcn.h>
void (*ucnv_convert)(const char *, const char *, char * , int32_t , const char *, int32_t,int32_t*) = 0;
bool openIcuuc()
{
	void* libFile = dlopen("/system/lib/libicuuc.so", RTLD_LAZY); 
	if (libFile)
	{
		ucnv_convert = (void (*)(const char *, const char *, char * , int32_t , const char *, int32_t,int32_t*))dlsym(libFile, "ucnv_convert_3_8");

		int index = 0;
		char fun_name[64];
		while (ucnv_convert == NULL)
		{
			sprintf(fun_name, "ucnv_convert_4%d", index++);
			ucnv_convert = (void (*)(const char *, const char *, char * , int32_t , const char *, int32_t,int32_t*))dlsym(libFile, fun_name);
			if (ucnv_convert) 
				return true;				
			if (++index > 11) 
				break;
		}
		dlclose(libFile);
	}
	return false;
} 
其次,就是轉換函數代碼如下:
const char* gb23122utf8(const char * gb2312)
{
	if (ucnv_convert == NULL)
	{
		openIcuuc();
	}		
	if (ucnv_convert)
	{
		int err_code = 0;
		int len = strlen(gb2312);
		char* str = new char[len * 2 + 10];    
		memset(str, 0, len * 2 + 10);
		ucnv_convert("utf-8", "gb2312", str, len * 2 + 10, gb2312, len, &err_code);
		if (err_code == 0)
		{
			return str;
		}
	}
	char test[256] = "gb23122utf8 error";
	char* str = new char[30]; 
	strcpy(str, test);
	return str;
}
好了,這就大功告成了,在幾臺安卓機上測試都OK,但是在模擬器上失敗,可能是缺少庫的問題。

當然如果有需要可以把這個接口暴露給lua使用。

static int luaA_Strg2u(lua_State *L)
{
	const char* gb2312 = luaL_checkstring(L, 1);
	const char* utf8 = gb23122utf8(gb2312);
	lua_pushstring(L, utf8);
	delete [] utf8;
	return 1;
}

void registerLuaFunction(lua_State* luaState)
{
	lua_register(luaState, "strg2u", luaA_Strg2u);	
	tolua_api4lua_open(luaState);
}

最後把我封裝的文件分享給大家吧!

關於cocos2dx中文轉UTF8碼的解決方案


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章