Conver QString to BSTR and vice versa - windows

I want to convert QString to BSTR and vice versa.
This is what i try to convert QString to BSTR :
std::wstring str_ = QString("some texts").toStdWString();
BSTR bstr_ = str_.c_str();
and to convert BSTR to QString :
BSTR bstr_;
wchar_t *str_ = bstr_;
QString qstring_ = QString::fromWCharArray(str_);
Is this correct? In other words is there any data lose? If yes, what is the
correct solution?

You should probably use SysAllocString to do this - BSTR also contains length prefix, which is not included with your code.
std::wstring str_ = QString("some texts").toStdWString();
BSTR bstr_ = SysAllocString(str_.c_str());
Other than that there isn't anything to be lost here - Both BSTR and QString use 16-bit Unicode encoding, so converting between each other should not modify internal data buffers at all.

To convert a BSTR to a QString you can simply use the QString::fromUtf16 function:
BSTR bstrTest = SysAllocString(L"ConvertMe");
QString qstringTest = QString::fromUtf16(bstrTest);

BSTR strings consist on two parts: four bytes for the string length; and the content it self which can contain null characters.
The short way to do it would be:
Convert QString to a two-byte null terminated string using QString::utf16. Do not use toWCharArray, a wide char is different on windows (two bytes) and linux (four bytes) (I know COM is microsoft tech, but better be sure)
Use SysAllocString to create a BSTR string that contains the string length already.
Optionally free the BSTR string with SysFreeString when you are done using it. Please read the following article to know when you need to release.
https://learn.microsoft.com/en-us/cpp/atl-mfc-shared/allocating-and-releasing-memory-for-a-bstr?view=vs-2017
BSTR bstr = ::SysAllocString(QString("stuff").utf16())
// use it
::SysFreeString(bstr)
To convert from BSTR to QString, you can reinterpret-cast BSTR to a ushort pointer, and then use QString::fromUtf16. Remember to free the BSTR when you are done with it.
QString qstr = QString::fromUtf16(reinterpret_cast<ushort*>(bstr));
The next useful article explains BSTR strings very well.
https://www.codeproject.com/Articles/13862/COM-in-plain-C-Part

BSTR oldStr;
QString newStr{QString::fromWCharArray(oldStr)};

Related

cannot convert const wchar_t* to const char*

ALL,
Can someone explain to me why this code:
std::wstring query1 = L"SELECT....";
res = mysql_query( m_db, m_pimpl->m_myconv.from_bytes( query1.c_str() ).c_str() );
gives me an error from the subject?
I do have -DUNICODE defined inside C++ options
I guess I just need a pair of fresh eyes.
Thank you.
It is on Gentoo Linux with gcc5.4.
This is a way to convert a unicode wide-character string to a const char*
char query_cstr[100];
size_t charsConverted;
wchar_t* unicode_query = L"SELECT * FROM table;";
wcstombs_s(&charsConverted, query_cstr, unicode_query, wcslen(unicode_query));
const char* query_const = query_cstr;
//Use query_const inside of mysql_query now that it's been converted to a const char*
I've run into trouble using the locale functions for various reasons. wcstombs_s() makes things a bit easier when converting unicode. Using c_str() on a std::wstring object will yield a const wchar_t* string, which is not what you want.

How wsprintf knows the length of lpFmt string?

wsprintf uses _cdecl calling convention just like printf. The latter pops from the stack an address of null-terminated format-string. But winapi definition of wsprintf uses LPCTSTR type, e.g. no null at the end.
I am wondering, how the length of the LPCTSTR lpFmt being computed? I mean, the function should stop reading the format buffer at some point. And it does. And it works.
LPCTSTR is null-terminated. It is
const char*
or
const wchar_t*
depending on whether or not you target Unicode. But either way, it is null-terminated.
LPCTSTR for UNICODE is defined as LPCWSTR and in msdn docs you can read that LPCWSTR is defined as:
A pointer to a constant null-terminated string of 16-bit Unicode
characters. For more information, see Character Sets Used
so wsprintf reads format until it finds L'\0' character. It is actually not written explicitly in wsprintf doc.
you are confusing many things
_cdecl defers from __stdcall by how to push arguments in the stack, it has nothing to do with NULL terminated strings.
then LPCTSTR, LPSTR, char* wchar *, all are NULL terminated strings (the difference is that some of them are Unicode while others as Ansi
other type of string that micrsoft uses it (and which is not mentioned here) is BSTR, BSTR is not a terminated string, its len is strored in buff[-1]; (BSTR is a string of 16bits chars, as Unicode)

How do you convert a 'System::String ^' to 'TCHAR'?

i asked a question here involving C++ and C# communicating. The problem got solved but led to a new problem.
this returns a String (C#)
return Marshal.PtrToStringAnsi(decryptsn(InpData));
this expects a TCHAR* (C++)
lpAlpha2[0] = Company::Pins::Bank::Decryption::Decrypt::Decryption("123456");
i've googled how to solve this problem, but i am not sure why the String has a carrot(^) on it. Would it be best to change the return from String to something else that C++ would accept? or would i need to do a convert before assigning the value?
String has a ^ because that's the marker for a managed reference. Basically, it's used the same way as * in unmanaged land, except it can only point to an object type, not to other pointer types, or to void.
TCHAR is #defined (or perhaps typedefed, I can't remember) to either char or wchar_t, based on the _UNICODE preprocessor definition. Therefore, I would use that and write the code twice.
Either inline:
TCHAR* str;
String^ managedString
#ifdef _UNICODE
str = (TCHAR*) Marshal::StringToHGlobalUni(managedString).ToPointer();
#else
str = (TCHAR*) Marshal::StringToHGlobalAnsi(managedString).ToPointer();
#endif
// use str.
Marshal::FreeHGlobal(IntPtr(str));
or as a pair of conversion methods, both of which assume that the output buffer has already been allocated and is large enough. Method overloading should make it pick the correct one, based on what TCHAR is defined as.
void ConvertManagedString(String^ managedString, char* outString)
{
char* str;
str = (char*) Marshal::StringToHGlobalAnsi(managedString).ToPointer();
strcpy(outString, str);
Marshal::FreeHGlobal(IntPtr(str));
}
void ConvertManagedString(String^ managedString, wchar_t* outString)
{
wchar_t* str;
str = (wchar_t*) Marshal::StringToHGlobalUni(managedString).ToPointer();
wcscpy(outString, str);
Marshal::FreeHGlobal(IntPtr(str));
}
The syntax String^ is C++/CLI talk for "(garbage collected) reference to a System.String".
You have a couple of options for the conversion of a String into a C string, which is another way to express the TCHAR*. My preferred way in C++ would be to store the converted string into a C++ string type, either std::wstring or std::string, depending on you building the project as a Unicode or MBCS project.
In either case you can use something like this:
std::wstring tmp = msclr::interop::marshal_as<std::wstring>( /* Your .NET String */ );
or
std::string tmp = msclr::interop::marshal_as<std::string>(...);
Once you've converted the string into the correct wide or narrow string format, you can then access its C string representation using the c_str() function, like so:
callCFunction(tmp.c_str());
Assuming that callCFunction expects you to pass it a C-style char* or wchar_t* (which TCHAR* will "degrade" to depending on your compilation settings.
That is a really rambling way to ask the question, but if you mean how to convert a String ^ to a char *, then you use the same marshaller you used before, only backwards:
char* unmanagedstring = (char *) Marshal::StringToHGlobalAnsi(managedstring).ToPointer();
Edit: don't forget to release the memory allocated when you're done using Marshal::FreeHGlobal.

How do I convert const wchar_t* to wchar_t or a multibyte char?

I need to send multibyte char to a socket after appending '\n' but what I have is a const wchar_t*. How can I convert it?
If your question is how to actually manipulate the contents of a constant, then consider const_cast.
Appending an '\n' to a const wchar_t* string means you have to make a copy of the original string. Read this MS docs on how to use swprintf for that:
http://msdn.microsoft.com/en-us/library/ybk95axf%28VS.71%29.aspx
If your problem is the conversion, the WideCharToMultiByte Function is your friend:
http://msdn.microsoft.com/en-us/library/dd374130%28VS.85%29.aspx
You don't need to use direct newline characters to do this:
const wchar_t* original(L"original value");
std::wostringstream streamVal;
streamVal << original << std::endl;
const std::wstring modified(streamVal.str());
Going through a _bstr_t seems a pain but allows you to do the wide char to multibyte conversion pretty easily (small code). Include comsuppw.lib in the list of libraries in your project.
#include "comutil.h"
_bstr_t bstrVal(modified.c_str());
const char* multibytes((const char*)bstrVal);
std::cout << multibytes; // includes newline
How can I convert const wchar_t* to wchar_t*?
reinterpret_cast<const wchar_t*>(L"Test");
Should really work.

convert BSTR to wstring

How to convert a char[256] to wstring?
update. here is my current code:
char testDest[256];
char *p= _com_util::ConvertBSTRToString(url->bstrVal);
for (int i = 0; i <= strlen(p); i++)
{
testDest[i] = p[i];
}
// need to convert testDest to wstring to I can pass it to this below function...
writeToFile(testDestwstring);
If your input is BSTR (as it seems to be) the data is already Unicode and you can just cast this directly to wstring as follows. _bstr_t has implicit conversions to both char* and wchar* which avoid the need for manual Win32 code conversion.
if (url->bstrVal)
{
// true => make a new copy - can avoid this if source
// no longer needed, by using false here and avoiding SysFreeString on source
const _bstr_t wrapper(url->bstrVal, true);
std::wstring wstrVal((const _wchar_t*)wrapper);
}
See here for more details on this area of Windows usage. It's easy to mess up the use of the Win32 API in this area - using the BSTR wrapper to do this avoids both data copy (if used judiciously) and code complexity.
MultiByteToWideChar will return a UTF-16 string. You need to specify the source codepage.

Resources