【问题标题】:How could I assign the value from lua_tostring() to a variable in type of wstring or const wchar_t* in utf-8如何将 lua_tostring() 中的值分配给 utf-8 中 wstring 或 const wchar_t* 类型的变量
【发布时间】:2021-08-21 06:48:52
【问题描述】:

函数lua_tostring()的返回值类型为const char*。但是,我有一个需要字符串作为参数的 C 函数。字符串为UTF-8编码格式的中文。

extern "C" LUALIB_API int PrintString(lua_State * L) {
    const char* str = lua_tostring(L, 1) // Get the string parameter 
                                         // And the string is actually in utf-8 in Lua.

    const WCHAR* str_w = .../* somehow makes str been an const WCHAR* */

    SomeFuncNeedWCHAR(str_w) // Imagine this func need a const WCHAR* as parameter. 

    return 0;
}

我尝试过使用MultiByteToWideChar()

    int size = MultiByteToWideChar(CP_UTF8, 0, str, -1, NULL, -1);

    WCHAR* buffer = new wchar_t[size * sizeof(wchar_t)];
    MultiByteToWideChar(CP_UTF8, 0, str, -1, buffer, size * sizeof(wchar_t));

    SomeFuncNeedWCHAR(buffer)

    delete[] buffer;

但我猜str实际上将char存储在UTF-8中,经过这种转换,它会将utf-8转换为utf-8。 (我的意思是,它转换两次)。所以我只想想办法把lua_tostring()的返回值解释成const WCHAR*

您基本上可以认为SomeFuncNeedWCHAR() 有一些类似的行为,例如MessageBoxExW() 以UTF-8 显示消息框。

所以我想知道如何解决这个问题。谢谢!

【问题讨论】:

  • after this conversion, it will convert a utf-8 to utf-8. - 这是不可能的。 MultiByteToWideChar() 从不转换为 UTF-8。
  • @EgorSkriptunoff 我不太明白这个函数是如何工作的。但是在文档上,它说 “此函数将字符串映射到宽字符 (Unicode) 字符串。”。无论如何,这个功能并没有像我预期的那样工作。但基本上,我只想将来自lua_tostring() 的字符串作为LPCWSTR 类型的参数传递。
  • size * sizeof(wchar_t) 应该只是size,除了你的代码看起来正确之外,你能更清楚地解释你遇到了什么问题吗?
  • @AlanBirtles 谢谢。基本上,我只想将 lua_tostring() 的返回值作为参数传递给 MessageBoxExW()。它需要一个LPCWSTR。我尝试使用MultiByteToWideChar() 将字符串转换为宽字符字符串。但是从 lua_tostring 得到的字符串值实际上在 Lua 中是 utf-8 格式的。最终结果是MultiByteToWideChar()转换后的消息框上的一些错误代码。所以我只是猜测它可能会再转换一次(不太确定)?
  • 错误代码是什么?请出示minimal reproducible example

标签: c++ winapi unicode lua


【解决方案1】:

你没有正确使用MultiByteToWideChar()

具体来说,您在第一次调用时将其cchWideChar 参数设置为-1,而此时它需要改为0

cchWideChar

lpWideCharStr 指示的缓冲区的大小(以字符为单位)。 如果此值为 0,则函数返回所需的缓冲区大小,以字符为单位,包括任何终止的空字符,并且不使用 lpWideCharStr 缓冲区。

即使它成功了,你也过度分配了buffer,这并不是严格意义上的错误,但它浪费了未使用的内存。

试试这个:

extern "C" LUALIB_API int PrintString(lua_State * L) {
    const char* str = lua_tostring(L, 1);

    int str_len = strlen(str) + 1; // avoid MBTWC() from needing to re-calculate the
                                   // same string length multiple times. Also include
                                   // the null terminator in the output...

    int w_len = MultiByteToWideChar(CP_UTF8, 0, str, str_len, NULL, 0);

    WCHAR* str_w = new WCHAR[w_len];
    MultiByteToWideChar(CP_UTF8, 0, str, str_len, str_w, w_len);

    SomeFuncNeedWCHAR(str_w);

    delete[] str_w;

    return 0;
}

【讨论】:

  • 是的!谢谢!它终于完美地解决了我的问题。我曾经认为cchWideChar 应该默认通过-1,就像cbMultiByte 一样。
  • @YZS 阅读documentationcchWideChar 根本不支持-1,只支持>= 0
  • @yzs cchWideChar 描述了输出缓冲区。 API 无法知道、计算或猜测其长度。它必须信任你。这与输入参数不同,例如 cbMultiByte,API 可以计算输入字符串的长度,前提是它是 NUL 终止的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-04-03
相关资源
最近更新 更多