【问题标题】:How to marshall utf-8 bytestring via COM variant?如何通过 COM 变体编组 utf-8 字节串?
【发布时间】:2016-03-03 21:53:30
【问题描述】:

我有一个代码可以通过 COM 变体传递一些 utf-8 编码的 JSON 字符串,特别是使用 CComVariant。一切正常,直到我的软件安装在日本用户的计算机上,我想他正在使用日语版本的 Windows 7。不知何故,Windows 决定更改 1 个非 ascii 字符的字节序列并破坏 JSON 格式。

组合问题:

"nić" (bytes: 0x22 0x6E 0x69 0xC4 0x87 0x22)

在它被打包到 CComVariant 然后解包回来之后上面的字符串变成了:

"niāE (bytes: 0x22 0x6E 0x69 0xC4 0x81 0x45)

即组合ć" 变成了āE

我的代码如下(简化版):

void get_json(VARIANT *out)
{
    const std::string json = "\"nić\"";
    CComVariant result = json.c_str();
    result.Detach(out);
}

然后在代码的其他部分:

CComVariant varJson;
get_json(&varJson);
const std::string utf8json = std::string(CStringA(varJson));
// At this point utf8json is not the same as original json above
// and cannot be decoded properly by JSON parser.

似乎我误解了 COM Variant 中关于 CStringA 的一些内容,并且在这里传递 UTF-8 字节并不安全。我无法在西欧版本的 Windows 上重现此问题,这与日文版本有某种关系。

【问题讨论】:

  • 源字符串以 utf-8 编码。但是 CComVariant 不知道,它会一直使用系统默认的代码页。它是 utf-8 的几率非常接近于零。嗯,零。您必须使用 std::wstring 来防止此类意外编码问题。从问题中不清楚需要从哪里开始,当然越早越好。如果您的 json 解析器太不稳定,那么使用 CP_UTF8 将自己转换为 MultiByteToWideChar()。
  • 唯一适用于 UTF-8 字节的 VARIANT 是一个字节数组。如果您从 UTF-8 转换为 UTF-16,则可以使用 BSTR — UTF-16 代码单元的计数序列。 (抱歉,如果我在这里更改 MFC、ATL 和 Win32 API 的组合。)

标签: c++ utf-8 com variant


【解决方案1】:

问题已在 cmets 中进行了解释。至于解决方案,因为您使用的是std(还有很多其他解决方案),我建议您使用此答案中定义的widen 函数:Is this code safe using wstring with MultiByteToWideChar? 并将代码更改为:

CComVariant result = widen(json).c_str();

让我们在调试器下检查一下。之前:

之后:

现在,VARIANT(或它包含的 BSTR)没问题。

请注意,如果您需要与此 VARIANT 或 BSTR 等效的字节字符串(真的吗?),请不要使用以下损坏的代码将其转换回来:std::string(CStringA(varJson)),再次使用与 @ 的反向等效项987654330@,这次基于WideCharToMultiByte

【讨论】:

    【解决方案2】:

    我找到了两种解决方法:

    1. (按照建议)将我的 json 对象的 utf-8 编码字符串表示形式转换为 Variant 预期的正确 unicode 字符串
    2. (稍微复杂一点)将我的字符串中的任何非 ascii 字符转换为 unicode-escape 序列,例如 \u1234,因此确保我的所有数据都是纯 ascii。

    由于向后兼容的限制,我不得不走第二条路线。

    【讨论】:

      猜你喜欢
      • 2020-03-09
      • 1970-01-01
      • 1970-01-01
      • 2013-05-11
      • 2016-05-20
      • 2016-04-23
      • 2010-12-05
      • 2012-01-20
      • 2020-09-15
      相关资源
      最近更新 更多