XMLCh到wchar_t,反之亦然
XMLCh to wchar_t and vice versa
我的配置:
- 编译器:gnu gcc 4.8.2
- 我用C++11编译
- 平台/OS:Linux 64位Ubuntu 14.04.1 LTS
我想用wchar_t*提供一个方法,并在许多需要XMLCh*的execerces库方法中使用它,但我不知道如何从一个方法转换到另一个方法。如果您使用char*而不是wchar_t*,这很容易,但我需要使用宽字符。在windows下,我可以很容易地从一个转换到另一个,但它在我的linux机器上不起作用。不知怎么的,我不得不手动将wchar_t*转换为XMLCh*
我链接到库libxerces-c-3.1.so,该库专门使用XMLCh*。XMLCh可以处理宽字符,但我不知道如何将其反馈给它,也不知道如何从XMLCh*返回wchar_t*
我开发了这个,但它不起作用(这里我吐出了一个wstring,它在清理内存时比指针更容易管理:
static inline std::wstring XMLCh2W(const XMLCh* tagname)
{
std::wstring wstr;
XMLSize_t len1 = XMLString::stringLen(tagname);
XMLSize_t outLen = len1 * 4;
XMLByte ut8[outLen+1];
XMLSize_t charsEaten = 0;
XMLTransService::Codes failReason; //Ok | UnsupportedEncoding | InternalFailure | SupportFilesNotFound
XMLTranscoder* transcoder = XMLPlatformUtils::fgTransService->makeNewTranscoderFor("UTF-8", failReason,16*1024);
unsigned int utf8Len = transcoder->transcodeTo(tagname,len1,ut8,outLen,charsEaten,XMLTranscoder::UnRep_Throw);// XMLTranscoder::UnRep_Throw UnRep_RepChar
ut8[utf8Len] = 0;
std::wstring wstr = std::wstring((wchar_t*)ut8);//I'm not sure this is actually ok to do
return wstr;
}
XMLCh由wchar_t(在windows上)或uint16_t(Linux上)定义,并使用UTF-16进行编码。
不幸的是,gcc 4.8.2不支持std::wstring_convert来转换unicode字符串的编码。但是您可以使用Boost的locale::conv::utf_to_utf()转换为XMLCh或从XMLCh转换。
#include <boost/locale.hpp>
static inline std::wstring XMLCh2W(const XMLCh* xmlchstr)
{
std::wstring wstr = boost::locale::conv::utf_to_utf<wchar_t>(xmlchstr);
return wstr;
}
static inline std::basic_string<XMLCh> W2XMLCh(const std::wstring& wstr)
{
std::basic_string<XMLCh> xmlstr = boost::locale::conv::utf_to_utf<XMLCh>(wstr);
return xmlstr;
}
如果要使用wchar_t*或XMLCh*,请使用下面的c_str()方法。
const wchar_t* wcharPointer = wstr.c_str();
const XMLCh* xmlchPointer = xmlstr.c_str();
不,在GCC下不能这样做,因为GCC将wchar_t
定义为32位UTF-32/UCS-4编码的字符串(出于实际目的,差异并不重要),而Xerces-c将XmlCh定义为16位UTF-16编码的字符串。
我发现最好的是使用C++11支持UTF-16字符串:
char16_t
和XmlCh
是等价的,但不能隐式转换;你仍然需要在它们之间做出选择。但至少与代码转换相比,这是便宜的std::basic_string<char16_t>
是等效的字符串类型- 使用形式为
u"str"
和u's'
的文字
不幸的是,VC++不支持C++11 UTF-16文字,尽管wchar_t
文字是UTF-16编码的。所以我在一个标题中得到了这样的东西:
#if defined _MSC_VER
#define U16S(x) L##x
typedef wchar_t my_u16_char_t;
typedef std::wstring my_u16_string_t;
typedef std::wstringstream my_u16_sstream_t;
inline XmlCh* XmlString(my_u16_char_t* s) { return s; }
inline XmlCh* XmlString(my_u16_string_t* s) { return s.c_str(); }
#elif defined __linux
#define U16S(x) u##x
typedef char16_t my_u16_char_t;
typedef std::basic_string<my_u16_char_t> my_u16_string_t;
typedef std::basic_stringstream<my_u16_char_t> my_u16_sstream_t;
inline XmlCh* XmlString(my_u16_char_t* s) { return reinterpret_cast<XmlCh*>(s); }
inline XmlCh* XmlString(my_u16_string_t* s) { return XmlString(s.c_str()); }
#endif
IMO,这是一个相当混乱的问题,但在VC++支持C++11 Unicode文本,允许Xerces直接用char16_t
重写之前,我看不出有什么问题会得到解决。
我最近处理过这个问题,现在Visual Studio 2015支持Unicode字符和字符串文字,这很容易用跨平台的方式处理。我使用以下宏和static_assert
来保证正确性:
#define CONST_XMLCH(s) reinterpret_cast<const ::XMLCh*>(u ## s)
static_assert(sizeof(::XMLCh) == sizeof(char16_t),
"XMLCh is not sized correctly for UTF-16.");
用法示例:
const XMLCh* features = CONST_XMLCH("Core");
auto impl = DOMImplementationRegistry::getDOMImplementation(features);
这是因为Xerces将XMLCh
定义为16位宽,并保存UTF-16字符串值,这与以u
为前缀的字符串文字标准给出的定义完全匹配。编译器不知道这一点,也不会在char16_t*
和XMLCh*
之间隐式转换,但使用reinterpret_cast
可以绕过这一点。如果出于任何原因,您试图在大小不匹配的平台上编译Xerces,static_assert
将失败,并引起人们对问题的关注。
- 在C++中,是否可以基于给定的标识符创建基类的新实例,反之亦然
- MacOS通过在莫哈韦"wchar.h"下破碎的自制啤酒发出叮当声
- 在C++中,将int值赋给enum,反之亦然
- VS Code C++:不准确的系统包括路径错误(wchar.h,boost/lambda/lambda.hpp)
- 如何在 c++ 中将所有大写字母转换为字符串中的小写字母,反之亦然?
- 将通用引用强制转换为可调用的 void 指针,反之亦然
- 用非原子更新原子变量,反之亦然
- 从向量到空指针的 memcpy(反之亦然)不起作用
- 'const char*'和'WCHAR*'
- 为什么需要与 WCHAR 相关的代码处理
- 将基类分配给派生对象,反之亦然,以C++以及静态和动态对象之间的差异
- 无法使用 mingw-w64 g++ 编译:找不到 <wchar.h>
- 如何在 OpenCL 中将小写转换为大写,反之亦然
- 无法将参数 1 从 WCHAR 转换为常量字符 *
- 无法使用 swprintf 在 WCHAR* 中打印字符*
- -fshort-wchar 和 std::wstring - 分段错误
- 如何将CNG密钥转换为OpenSSL EVP_PKEY(反之亦然)?
- 我应该使用 wchar 还是 char 来加密?
- C++ - 使用结构数据类型将单词中的单个小写字符更改为大写,反之亦然
- 如何在C++中将WCHAR*转换为字符串,反之亦然