How do I convert the contents of a Platform::String to be used by functions that expect a char* based string? I'm assuming WinRT provides helper functions for this but I just can't find them.
Thanks!
How do I convert the contents of a Platform::String to be used by functions that expect a char* based string? I'm assuming WinRT provides helper functions for this but I just can't find them.
Thanks!
Platform::String::Data()
will return a wchar_t const*
pointing to the contents of the string (similar to std::wstring::c_str()
). Platform::String
represents an immutable string, so there's no accessor to get a wchar_t*
. You'll need to copy its contents, e.g. into a std::wstring
, to make changes.
There's no direct way to get a char*
or a char const*
because Platform::String
uses wide characters (all Metro style apps are Unicode apps). You can convert to multibyte using WideCharToMultiByte
.
WideCharToMultiByte
is callable from a Metro style app. –
Posehn String
is immutable, why does String::Begin
return a char16 *
and not a char16 const*
? Is it legal to modify an individual character using this pointer? –
Those Begin()
and End()
both return char16 const*
. You can see their definitions in <vccorlib.h>
. You may not modify the pointed-to characters (strings are reference counted, and if there are other owners and you modify the string, those other owners will be very surprised to discover that their string has changed). I'll see what I can do to get the documentation fixed. Thanks for the heads-up. –
Posehn Here is a very simple way to do this in code w/o having to worry about buffer lengths. Only use this solution if you are certain you are dealing with ASCII:
Platform::String^ fooRT = "aoeu";
std::wstring fooW(fooRT->Begin());
std::string fooA(fooW.begin(), fooW.end());
const char* charStr = fooA.c_str();
Keep in mind that in this example, the char*
is on the stack and will go away once it leaves scope
std::string
line generates compile messages is there any way to get around this? see reference to function template instantiation 'std::basic_string<char,std::char_traits<char>,std::allocator<char>>::basic_string<std::_String_iterator<std::_String_val<std::_Simple_types<_Elem>>>,0>(_Iter,_Iter,const _Alloc &)' being compiled with [ _Elem=wchar_t, _Iter=std::_String_iterator<std::_String_val<std::_Simple_types<wchar_t>>>, _Alloc=std::allocator<char> ]
–
Ortensia Platform::String::Data()
will return a wchar_t const*
pointing to the contents of the string (similar to std::wstring::c_str()
). Platform::String
represents an immutable string, so there's no accessor to get a wchar_t*
. You'll need to copy its contents, e.g. into a std::wstring
, to make changes.
There's no direct way to get a char*
or a char const*
because Platform::String
uses wide characters (all Metro style apps are Unicode apps). You can convert to multibyte using WideCharToMultiByte
.
WideCharToMultiByte
is callable from a Metro style app. –
Posehn String
is immutable, why does String::Begin
return a char16 *
and not a char16 const*
? Is it legal to modify an individual character using this pointer? –
Those Begin()
and End()
both return char16 const*
. You can see their definitions in <vccorlib.h>
. You may not modify the pointed-to characters (strings are reference counted, and if there are other owners and you modify the string, those other owners will be very surprised to discover that their string has changed). I'll see what I can do to get the documentation fixed. Thanks for the heads-up. –
Posehn You shouldn't cast a wide character to a char, you will mangle languages using more than one byte per character, e.g. Chinese. Here is the correct method.
#include <cvt/wstring>
#include <codecvt>
Platform::String^ fooRT = "foo";
stdext::cvt::wstring_convert<std::codecvt_utf8<wchar_t>> convert;
std::string stringUtf8 = convert.to_bytes(fooRT->Data());
const char* rawCstring = stringUtf8.c_str();
char* raw = std::wstring_convert<std::codecvt_utf8<wchar_t>>().to_bytes(fooRT->Data()).c_str();
–
Synchronous raw
variable will point to deallocated memory (temporary object is gone after expression is evaluated) if used literally. Better use std::string utf8 = std::wstring_convert<std::codecvt_utf8<wchar_t>>().to_bytes(fooRT->Data())
unless you are sure what you are doing. –
Booze There's the String::Data
method returning const char16*
, which is the raw unicode string.
Conversion from unicode to ascii or whatever, i.e. char16*
to char*
, is a different matter. You probably don't need it since most methods have their wchar
versions these days.
A solution using wcstombs:
Platform::String^ platform_string = p_e->Uri->AbsoluteUri;
const wchar_t* wide_chars = platform_string->Data();
char chars[512];
wcstombs(chars, wide_chars, 512);
wcstombs
generates this warning 'wcstombs': This function or variable may be unsafe. Consider using wcstombs_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS.
–
Ortensia Solution 1:
#include <cvt/wstring>
#include <codecvt>
Platform::String^ tTextRT = "TestText";
stdext::cvt::wstring_convert<std::codecvt_utf8<wchar_t>> convert;
std::string stringUtf8 = convert.to_bytes(tTextRT->Data());
const char* rawCstring = stringUtf8.c_str();
But this solution generate error.
Error C4996 'stdext::cvt': warning STL4044: The contents of the stdext::cvt namespace are non-Standard extensions and will be removed in the future. The MultiByteToWideChar() and WideCharToMultiByte() functions can be used instead. You can define _SILENCE_STDEXT_CVT_DEPRECATION_WARNING or _SILENCE_ALL_MS_EXT_DEPRECATION_WARNINGS to suppress this warning.
Solution 2:
Platform::String^ testText = "Test Text";
std::wstring tTextW(testText->Begin());
std::string tTextA(tTextW.begin(), tTextW.end());
const char* charStr = tTextA.c_str();
But this solution has another Issue:
Any character outside the range of ASCII characters will just be destroyed to a random representation, depending on the executing threads current state.
Workable Solution:
#include <cvt/wstring>
#include <stringapiset.h>
Platform::String^ testText = "foo";
const wchar_t* pWStr = testText->Data();
int bufferSize = WideCharToMultiByte(CP_UTF8, 0, pWStr, -1, NULL, 0, NULL, NULL);
char* stringUtf8 = new char[bufferSize + 1];
memset(stringUtf8, 0, bufferSize + 1);
if (0 == WideCharToMultiByte(CP_UTF8, 0, pWStr, -1, stringUtf8, bufferSize, NULL, NULL))
{
throw std::exception("Can't convert string to Unicode");
}
const char* rawCstring = std::string(stringUtf8).c_str();
delete[] stringUtf8;
© 2022 - 2024 — McMap. All rights reserved.