这是一个事实上已经解决的,但是却很难搜索到方案的问题。在这点上不得不佩服老外的兜圈子和中国人的没耐性。关于这个问题比较详细的文档是lua-suers wiki上的一篇http://lua-users.org/wiki/LuaUnicode ,看完之后,虽然懂了不少,还是没解。这点也怪不得人家,Unicode的问题对于东亚语系才是不得不解决的问题。倒是中文资料总是三言两语带过,确实让人很愤懑。
总的来说,就是lua因为使用长度来标示字符串的长度,所以在一个字符串里面储存Unicode的字符是没有问题的。因此,要使得lua中的字符串能够直接被使用Unicode的系统使用,只需要开始的时候将字符串转换为Unicode保存在lua的字符串中就可以了。
也就是注册一个mbs2uni的函数到lua环境,然后定义字符串的时候用s=mbs2uni("xxxx")这样的语句就可以了。缺点就是有些针对字符串的操作有可能不能正确执行,但其实很多情况,我们只是需要在程序中保存一个字符串而已。
因为从UTF-8到Unicode是很容易的,推荐做法是把lua的源程序保存为UTF-8格式,这样只需要提供一个utf8ToUnicode16的函数就可以了,而这个函数是很容易自己实现的,从而增加了移植性。
这个函数恒定返回转换utf8字符串需要的数组大小,并在转换后的Unicode字符串的最后面加一个L'/0'。
- int utf8ToUnicode16( const char * utf8, WChar* unicode16, int length) {
- char c;
- int i = 0;
- --length;
- while (c = *utf8) {
- if (c & 0x80) {
- if (c & 0x20) {
- if (i < length) {
- unicode16[i] = ((utf8[0] & 0xf) << 12) | ((utf8[1] & 0x3f) << 6) | ((utf8[2] & 0x3f));
- }
- ++i;
- utf8 += 3;
- } else {
- if (i < length) {
- unicode16[i] = ((utf8[0] & 0x1f) << 6) | ((utf8[1] & 0x3f));
- }
- ++i;
- utf8 += 2;
- }
- } else {
- if (i < length) {
- unicode16[i] = c;
- }
- ++i;
- ++utf8;
- }
- }
- if (i <= length) {
- unicode16[i] = 0;
- }
- return i + 1;
- }
注册到lua环境中的函数
- static int l_utf8ToUnicode16(lua_State* L) {
- WChar a[256];
- WChar* unicode16 = a;
- int length = 0;
- const char * utf8;
- utf8 = luaL_checkstring(L, 1);
- length = utf8ToUnicode16(utf8, unicode16, 256);
- if (length <= 256) {
- lua_pushlstring(L, ( const char *) unicode16, length * 2);
- } else {
- unicode16 = (WChar*)malloc(length);
- utf8ToUnicode16(utf8, unicode16, length);
- lua_pushlstring(L, ( const char *) unicode16, length * 2);
- free(unicode16);
- }
- return 1;
- }