Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How would you convert a std::string to BSTR*?

Tags:

c++

winapi

bstr

How would you convert a std::string to BSTR*?

STDMETHODIMP CMyRESTApp::rest(BSTR data, BSTR* restr)
{
    RESTClient restclient;
    RESTClient::response resp = restclient.get(data);

    Log("Response Status code: %s", resp.code);
    Log("Response Body: %s", resp.body);

    *restr = // here
    return S_OK;
}

I need convert the resp.body and this then to be returned for the *restr here.

like image 859
xkm Avatar asked Jul 09 '15 10:07

xkm


2 Answers

An ATL based approach is to use ATL::CComBSTR and then a Detach() (or CopyTo(...)) the resultant CComBSTR to the BSTR*

Something like:

CComBSTR temp(stlstr.c_str());
*restr = temp.Detach();

Else in general for std::basic_string you can use the Win32 API Sys* family of functions, such as SysAllocStringByteLen and SysAllocString;

// For the `const char*` data type (`LPCSTR`);
*restr = SysAllocStringByteLen(stlstr.c_str(), stlstr.size());

// More suitable for OLECHAR
*restr = SysAllocString(stlwstr.c_str());

OLECHAR depends on the target platform, but generally it is wchar_t.

Given your code, the shortest snippet could just be;

*restr = SysAllocStringByteLen(resp.body.c_str(), resp.body.size());

Note these Windows API functions use the "usual" windows code page conversions, please see further MSDN documentation on how to control this if required.

like image 107
Niall Avatar answered Sep 20 '22 00:09

Niall


std::string is made by chars; BSTR is usually a Unicode UTF-16 wchar_t-based string, with a length prefix.

Even if one could use a BSTR as a simple way to marshal a byte array (since the BSTR is length-prefixed, so it can store embedded NULs), and so potentially a BSTR could be used also to store non-UTF-16 text, the usual "natural" behavior for a BSTR is to contain a Unicode UTF-16 wchar_t-string.

So, the first problem is to clarify what kind of encoding the std::string uses (for example: Unicode UTF-8? Or some other code page?). Then you have to convert that string to Unicode UTF-16, and create a BSTR containing that UTF-16 string.

To convert from UTF-8 (or some other code page) to UTF-16, you can use the MultiByteToWideChar() function. If the source std::string contains a UTF-8 string, you can use the CP_UTF8 code page value with the aforementioned API.

Once you have the UTF-16 converted string, you can create a BSTR using it, and pass that as the output BSTR* parameter.

The main Win32 API to create a BSTR is SysAllocString(). There are also some variants in which you can specify the string length.

Or, as a more convenient alternative, you can use the ATL's CComBSTR class to wrap a BSTR in safe RAII boundaries, and use its Detach() method to pass the BSTR as an output BSTR* parameter.

CComBSTR bstrResult( /* UTF-16 string from std::string */ );
*restr = bstrResult.Detach();

Bonus reading:

Eric's Complete Guide To BSTR Semantics

like image 44
Mr.C64 Avatar answered Sep 22 '22 00:09

Mr.C64