2014-09-15 9 views
1

내 설정 :XMLCh는 wchar_t를하고 그 반대의 경우도 마찬가지

  • 컴파일러 : GNU GCC 나 C++ 11
  • 플랫폼/OS 컴파일 4.8.2
  • : 리눅스 64 비트 우분투 14.04.1 LTS

wchar_t *를 사용하여 메서드를 제공하고 XMLC *가 필요한 많은 xecerces 라이브러리 메서드에서 사용하려는 경우 하나에서 다른 것으로 변환하는 방법을 모르겠습니다. wchar_t * 대신 char *를 사용하면 쉽지만 와이드 문자를 사용해야합니다. Windows에서 나는 쉽게 하나에서 다른 캐스팅 수 있지만 내 리눅스 컴퓨터에서 작동하지 않습니다. 어떻게 든 수동으로 wchar_t *를 XMLCh로 변환해야합니다.

XMLCh *를 독점적으로 사용하는 라이브러리 libxerces-c-3.1.so를 링크합니다. XMLCh는 와이드 캐릭터를 처리 할 수 ​​있지만, XMLChar *를 XMLCh에서 가져 오는 방법도 알지 못합니다.

이 코드는 개발되었지만 작동하지 않습니다. 포인터보다 메모리를 청소에서 쉽게 관리 할 수있는 형식 wstring 아웃 : GCC는 32 비트, UTF-32/UCS로 wchar_t을 정의하기 때문에

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; 
} 
+0

중복 된 http://stackoverflow.com/questions/25782247/xerces-c-and-cross-platform-string-literals. 여기서 얻은 것보다 더 많은 대답을 얻을 수는 없을 것입니다. – Tom

답변

1

아니, 당신은, GCC에서 그렇게 할 수 없습니다 Xerces-c는 XmlCh를 16 비트 UTF-16으로 인코딩 된 문자열로 정의합니다.

C++을 사용하는 것이 최선의 방법입니다 (실제로는 차이가 없습니다). 11 초 UTF-16 문자열 upport를 :

  • char16_tXmlCh 및 암시 적 변환 아니지만, 등가이고; 당신은 여전히 ​​그들 사이에 캐스트해야합니다. 그러나 적어도 이것은 트랜스 코딩과 비교하여 저렴합니다.
  • std::basic_string<char16_t>은 동일한 문자열 유형입니다.
  • u"str"u's' 형태의 리터럴을 사용하십시오.

wchar_t 리터럴은 UTF-16으로 인코딩되었지만 VC++는 C++ 11 UTF-16 리터럴을 지원하지 않습니다. 그래서 헤더에이 같은 끝낼 : 그것은에 Xerces를 허용, IMO, C++ 11 유니 코드 리터럴 내가 ++ VC까지 정리하기를 참조 할 수 있습니다 오히려 엉망 아니라 하나의 지원입니다

#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 

char16_t의 관점에서 직접 재 작성하십시오.

+0

감사합니다. 굉장히 유용하다. – mimosa

+0

문제 없습니다. 하지만 스트림이 특별한 마술없이 작동하지 않는다는 것을 알아 두십시오. 특히 std :: ctype , std :: numpunct 및 std :: codecvt (마지막 하나는 잘못된 것일 수 있습니다. 길 주변에). 그런 다음 해당 패싯을 std :: num_get 및 std :: num_put 전역 로캘에 추가해야합니다. – Tom

+0

Xersesc define _NATIVE_WCHAR_T_DEFINED – KindDragon

2

XMLCh는 wchar_t (Windows의 경우) 또는 uint16_t (Linux의 경우)로 정의되며 UTF-16으로 인코딩됩니다.

gcc 4.8.2는 유니 코드 문자열의 인코딩을 변환하기 위해 std :: wstring_convert를 지원하지 않습니다. 하지만 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(); 
1

나는 최근에이 문제를 다루어, 지금은 비주얼 스튜디오 2015은 유니 코드 문자 및 문자열 리터럴을 지원하는 것으로,이 크로스 플랫폼 방식으로 처리하는 것이 매우 쉽다. 사용의

#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."); 

예 : 나는 정확성을 보장하기 위해 다음과 같은 매크로 static_assert을 사용 Xerces에 16 비트 폭으로하고, UTF-16 문자열 값을 유지하기 위해 XMLCh을 정의하기 때문에

const XMLCh* features = CONST_XMLCH("Core"); 
auto impl = DOMImplementationRegistry::getDOMImplementation(features); 

이 작동 u이라는 접두사가 붙은 문자열 리터럴에 대한 표준에서 제공하는 정의와 완벽하게 일치합니다. 컴파일러는이를 모르고 char16_t*XMLCh* 사이를 암시 적으로 변환하지 않지만 reinterpret_cast으로이 문제를 해결할 수 있습니다. 그리고 크기가 일치하지 않는 플랫폼에서 Xerces를 컴파일하려고하는 이유가 무엇이든간에 static_assert은 실패하고 문제에 대해주의를 환기시킵니다.

+0

을 사용할 수 있습니다. 매우 흥미 롭습니다. 어떤 C++ 버전이이를 지원합니까? – mimosa

+0

UTF-16 리터럴과'char16_t' 원시 타입은 C++ 11의 표준에 추가되었으므로 (GCC 나 Clang의 모든 최신 버전에는 포함되어 있어야합니다), MSVC는 VS2015까지 지원하지 않습니다. –