如何将UTF16的ushort数组转换为UTF8的std::string?

7

目前我正在编写一个插件,它只是一个现有库的包装器。

插件的宿主向我传递一个 utf-16 格式的字符串,定义如下:

typedef unsigned short PA_Unichar;

而被包装的库仅接受 const char* 或 std::string utf-8 格式的字符串。我尝试编写一个转换函数,如下所示:

std::string toUtf8(const PA_Unichar* data)
{
std::wstring_convert<std::codecvt_utf8_utf16<char16_t>,char16_t> convert;
return std::string(convert.to_bytes(static_cast<const char16_t*>(data));
}

但显然这样做是不行的,会抛出编译错误:“static_cast from 'const pointer' (aka 'const unsigned short*') to 'const char16_t *' is not allowed”

那么最优雅/正确的方法是什么呢?

提前感谢您。


在您的平台上,std::is_same<unsigned short, char16_t>::value 的值是多少?另外,使用的编译器是哪个? - moshbear
std::is_same<unsigned short, char16_t>::value 的值为0(false),我正在使用苹果LLVM编译器4.1在Mac上进行编译,同时也使用Visual Studio 2012进行交叉编译。 - Robotex
1
根据http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2018.html,`char16_t`是`uint16_least_t`,而不是`uint16_t`。在您的平台上,看起来`uint16_least_t`没有别名为`unsigned short,因此sizeof(char16_t) != sizeof(unsigned short)。当底层的sizeof不匹配时,指针类型上的static_cast`将失败。 - moshbear
1
char16_t 从定义上来看是16位的。如果unsigned short用于UTF-16,那么它也必须是16位的。我要么将PA_Unicode更改为uint16_t,要么使用reinterpret_cast代替static_cast - Remy Lebeau
在看到答案之前,我使用了后一种方式,当然我可以替换typedef,但由于我不维护API,我不能冒险在每次更新时破坏代码。我希望编写接口的人只使用标准类型。 - Robotex
现在有标准的char16_tchar32_t类型(它们是C++11中的新类型,但是在C11中是现有类型的typedef),因此很可能库将开始使用它们。 ICU库已经支持将其构建为C++11,在这种情况下,它使用标准的charNN_t类型。 - Jonathan Wakely
1个回答

2

您可以使用basic_string(Iterator, Iterator)构造函数将PA_unichar字符串转换为char16_t字符串,然后像您尝试的那样使用std::codecvt_utf8_utf16 facet:

std::string conv(const PA_unichar* str, size_t len)
{
  std::u16string s(str, str+len);
  std::wstring_convert<std::codecvt_utf8_utf16<char16_t>,char16_t> convert;
  return convert.to_bytes(s);
}

我认为这是正确的。不幸的是,由于我的实现尚未支持它,我无法进行测试。我有一个wstring_convert 的实现,计划将其包含在GCC 4.9中,但我没有codecvt_utf8_utf16 的实现来进行测试。


非常感谢,看起来运行良好,这也让我避免了一些可怕的类型转换 :) - Robotex
太好了,我很高兴我脑海中的编译器正确地进行了类型检查!顺便问一下,你使用的是哪个支持这些类的编译器? - Jonathan Wakely
我在基于Mac系统上使用LLVM 4.1编译器(设置了标志“-std=c++11”)进行编译,并在Windows系统上使用Visual Studio 2012。 - Robotex
2
谢谢你的信息 - 我想如果竞争对手有它,我最好完成我的GCC实现!我没有看到任何对这些课程的需求,我认为大多数人甚至不知道它们的存在。 - Jonathan Wakely
1
糟糕,gcc 4.8 中没有codecvt_utf8_utf16。希望Jonathan Wakely能赶在gcc 4.9截止日期之前完成。对我来说太晚了。 - BSalita

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