将Platform::String转换为std::string

4

我在Windows Phone 8项目的Cocos2dx游戏中,从C#组件回调中获取了包含印度语言字符的String^。每当我将其转换为std::string时,印地语和其他字符就会变成垃圾字符。我无法找到原因。

以下是示例代码,这里只定义了Platform::String^,但请考虑从C#组件传递给C++ WinRT Component

String^ str = L"विकास, વિકાસ, ਵਿਕਾਸ, Vikas";
std::wstring wsstr(str->Data());
std::string res(wsstr.begin(), wsstr.end());

你能把它保留为 wstring 吗? - Peter Torr - MSFT
@PeterTorr-MSFT,“wstring”内容与“String ^”相同,但问题在于将其转换为“std :: string”时会丢失非英语字符的编码。 - Vikas Patidar
2个回答

7
编辑:请参见此答案以获取更好的可移植解决方案。
问题在于std::string仅包含8位字符数据,而您的Platform::String^包含Unicode数据。Windows提供了WideCharToMultiByteMultiByteToWideChar函数来进行相互转换:
std::string make_string(const std::wstring& wstring)
{
  auto wideData = wstring.c_str();
  int bufferSize = WideCharToMultiByte(CP_UTF8, 0, wideData, -1, nullptr, 0, NULL, NULL);
  auto utf8 = std::make_unique<char[]>(bufferSize);
  if (0 == WideCharToMultiByte(CP_UTF8, 0, wideData, -1, utf8.get(), bufferSize, NULL, NULL))
    throw std::exception("Can't convert string to UTF8");

  return std::string(utf8.get());
}

std::wstring make_wstring(const std::string& string)
{
  auto utf8Data = string.c_str();
  int bufferSize = MultiByteToWideChar(CP_UTF8, 0, utf8Data, -1, nullptr, 0);
  auto wide = std::make_unique<wchar_t[]>(bufferSize);
  if (0 == MultiByteToWideChar(CP_UTF8, 0, utf8Data, -1, wide.get(), bufferSize))
    throw std::exception("Can't convert string to Unicode");

  return std::wstring(wide.get());
}

void Test()
{
  Platform::String^ str = L"विकास, વિકાસ, ਵਿਕਾਸ, Vikas";
  std::wstring wsstr(str->Data());
  auto utf8Str = make_string(wsstr); // UTF8-encoded text
  wsstr = make_wstring(utf8Str); // same as original text
}

1
非常感谢 :) std::make_unique 只适用于通用 C++ 项目 WP 8.1,对于旧平台如 WP8.0,我必须使用 char 数组。我已经找到了一个例子 https://github.com/cocos2d/cocos2d-x/blob/cocos2d-x-2.2.6/extensions/GUI/CCEditBox/CCEditBoxImplWp8.cpp - Vikas Patidar
使用标准库 std::codevect 有什么问题吗? - Guy
@gMorphus,我之前不知道这个,所以感谢你的提示(顺便说一下,对于其他人来说,它是std::codecvt,可以在此处查找)。实际上,根据这个答案给出的另一个问题,它甚至更容易。 - Peter Torr - MSFT

2

使用C++,您可以通过以下代码从Platform::String转换为std::string:

Platform::String^ fooRT = "aoeu";
std::wstring fooW(fooRT->Begin());
std::string fooA(fooW.begin(), fooW.end());

参考资料: 如何将Platform::String转换为char*?

这是我找到的最短的前向方式。 - visc
这对于OP的示例有效吗?最后两个语句基本上与问题中的相同,将截断宽字符为8位并且会丢失信息。 - uliwitness
使用Begin(),而不是Data()。 - Luis B
@uliwitness 你是对的,这个解决方案在平台字符串中不适用于Unicode数据。 - Jatin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接