18

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!

R. Martinho Fernandes
  • 228,013
  • 71
  • 433
  • 510
djcouchycouch
  • 12,724
  • 13
  • 69
  • 108

5 Answers5

15

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

rysama
  • 1,674
  • 16
  • 28
  • 3
    For every problem, there is a solution, that's simple, elegant. And wrong. Like this one. Any character outside the range of ASCII characters will just be butchered to a random representation, depending on the executing threads current state. **Don't use this solution.** (Which is easy, because it doesn't even compile.) – IInspectable Oct 24 '16 at 01:56
  • Fixed the compiler error. PS: Still a nice way of converting if 100% sure that you only have to deal with ASCII characters – bas Nov 05 '16 at 21:16
  • the `std::string` line generates compile messages is there any way to get around this? `see reference to function template instantiation 'std::basic_string,std::allocator>::basic_string>>,0>(_Iter,_Iter,const _Alloc &)' being compiled with [ _Elem=wchar_t, _Iter=std::_String_iterator>>, _Alloc=std::allocator ]` – escape-llc Apr 13 '22 at 15:59
13

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.

James McNellis
  • 348,265
  • 75
  • 913
  • 977
  • Are there any Metro-specific "indirect" methods of converting to char* ? – djcouchycouch Jul 31 '12 at 18:20
  • `WideCharToMultiByte` is callable from a Metro style app. – James McNellis Jul 31 '12 at 18:21
  • @JamesMcNellis If `String` is immutable, why does [`String::Begin`](http://msdn.microsoft.com/en-us/library/windows/apps/hh825849.aspx) return a `char16 *` and not a `char16 const*`? Is it legal to modify an individual character using this pointer? – Praetorian Sep 21 '12 at 16:24
  • @Prætorian: The documentation is wrong. `Begin()` and `End()` both return `char16 const*`. You can see their definitions in ``. 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. – James McNellis Sep 21 '12 at 16:42
  • 4
    this doesn't answer the question. He asked how to convert from a Platform::String to a char* and there are ways to do this. WideCharToMultiByte works but someone new to the function would have no idea how to use it. – Eric Nov 14 '13 at 23:06
  • Also a wchar_t* from HString::GetRawBuffer is using the WRL and WindowsGetStringRawBuffer if using the true HSTRING. – Dwayne Robinson Mar 28 '15 at 07:32
  • @Eric: The OP never mentioned their destination character string encoding. Without that information, this answer is as complete as it gets (although it could have asked for the missing information). Then again, you could have left a comment on it, to explain why this is important just as well. – IInspectable Oct 24 '16 at 02:05
8

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();
Kris
  • 15
  • 7
Jeff McClintock
  • 1,242
  • 10
  • 27
  • Or one linear without using stdext `char* raw = std::wstring_convert>().to_bytes(fooRT->Data()).c_str();` – Quest Sep 11 '15 at 16:01
  • 2
    But using @Quest's method, the `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>().to_bytes(fooRT->Data())` unless you are sure what you are doing. – Emil Styrke Nov 21 '17 at 12:28
  • this solution doesn't generate any compiler messages! – escape-llc Apr 13 '22 at 16:07
1

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.

Qnan
  • 3,714
  • 18
  • 15
  • 2
    Alas, for I do not live in a wchar world. Most of the code I'm working with is legacy code that expects 8 bit chars strings. :) – djcouchycouch Jul 31 '12 at 18:16
1

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);
Sistr
  • 1,175
  • 10
  • 26
  • `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.` – escape-llc Apr 13 '22 at 16:00
  • I guess the warning explain it all, using wcstombs_s is safer at the expense of some extra verbosity. – Sistr Apr 18 '22 at 06:11
  • your comment provides no useful information, since myself and others coming here are not all C++/windows experts (I was trying to do some C# interop), I was relaying what the compiler told me while trying the answers on this page. maybe you could update your answer and provide more value? – escape-llc Apr 19 '22 at 16:16