0

Now I am doing a Windows Metro App job, and I am developing a C++ component to get the input method's candidate List.

An issue occurs at the last step to output the result list. I can get each member of the candidate list, but the type is the "Bstr", to get them in the Metro App, I have to convert them into the type of "Platform::String".

How to convert Bstr to Platform::String?

I really appreciate any help you can provide.

CzeRen
  • 11
  • 4
  • A `BSTR` is a pointer to a nullterminated UTF-16 encoded string, with a 16-bit (I think it was) string length preceding the character pointed to. Depending on the encoding of a `Platform::String` you may have to do some conversion. Using the C++ standard library that would be via `std::codecvt`. – Cheers and hth. - Alf Nov 13 '15 at 06:28

2 Answers2

1

The Platform::String constructor overloads make this very easy:

BSTR comstr = SysAllocString(L"Hello world");
auto wrtstr = ref new Platform::String(comstr);

To be perfectly complete, both BSTR and a WinRT string can contain an embedded 0. If you want to handle that corner case then:

BSTR comstr = SysAllocStringLen(L"Hello\0world", 11);
auto wrtstr = ref new Platform::String(comstr, SysStringLen(comstr2));
Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
  • Are you sure it is safe to cast `wchar_t*` to `char16_t*`? Both (`wchar_t` and `char16_t`)types are different internal types, not just typedefs of another. I couldn't find any reference stating that a cast would be safe. – Simon Kraemer Nov 13 '15 at 14:08
  • There are no casts in these tested code snippets. Makes it pretty hard to figure out what you might be talking about. char16_t was necessary for Unix, it is irrelevant on Windows. There's only one kind of utf-16 encoding. – Hans Passant Nov 13 '15 at 14:12
  • Maybe I'm totally wrong here, but if you look at my answer and the links to the MSDN I posted it might become more clear what I mean. `BSTR` is `wchar*` while `Platform::String` awaits a `char16*`. According to [MSDN](https://msdn.microsoft.com/en-us/library/mt228149.aspx) and [cppreference.com`](http://en.cppreference.com/w/cpp/language/types) both character types represent UTF-16 characters, yet are distinct types. I just want to know whether casting between these types is safe as the internal binary representation of both types might be different (e.g. different complement). – Simon Kraemer Nov 13 '15 at 14:22
  • As I said, there is no casting here and the difference is irrelevant. Most visible by the platform.winmd metadata file *declaring* the constructor with const wchar_t*, the one the compiler uses and IntelliSense shows, and the *implementation* in vccorlib.h file using const char16_t*. The metadata definition predates Microsoft actually implemented char16_t. – Hans Passant Nov 13 '15 at 14:32
  • So the `char16*` is just saying to pass a UTF-16 string? I'm fine with that. Maybe sometime someone adjusts the MSDN page to avoid such a confusion. – Simon Kraemer Nov 13 '15 at 14:56
0

According to MSDN ([1],[2]) we have this definitions:

#if !defined(_NATIVE_WCHAR_T_DEFINED)
typedef unsigned short WCHAR;
#else
typedef wchar_t WCHAR;
#endif
typedef WCHAR OLECHAR;
typedef OLECHAR* BSTR; 

So BSTR is of type wchar_t* or unsigned short*, or a null terminated 16-bit string.

From what I see from the documentation of Platform::String the constructor accepts a null-terminated 16-bit string as const char16*

While char16 is guaranteed represent UTF16, wchar is not.

UPDATE: As Cheers and hth. - Alf pointed out the line above isn't true for Windows/MSVC. I couldn't find any information on whether it is safe to cast between both types in this case. Since both wchar_t and char16_t are different integrated types I would still recommend to use std::codecvt to avoid problems.

So you should use std::codecvt to convert from wchar_t* to char16_t* and pass the result to the constructor of your Platform::String.

Community
  • 1
  • 1
Simon Kraemer
  • 5,700
  • 1
  • 19
  • 49