2

I'm working with a Microsoft Kinect SDK where functions return BSTR. I need to get a QString or std::string.

Here's what I've tried:

BSTR bstr = s->NuiUniqueId();

// QString qs((QChar*)bstr, SysStringLen(bstr));

std::wstring ws(bstr);

ui->lblDetails->setText(QString::fromStdWString(ws));

With this solution the program crashes. With the line that is commented out I get "unresolved external symbol SysStringLen".

Is SysStringLen the way to go, but I need to add some additional libraries (wouldn't the API include it already) or is there another solution?


Additional question: why does Microsoft do it? I mean:

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

What's the reason behind stuff like this? And even if they find it beneficial to use it internally, couldn't they just use normal char array or std::(w)string in the API to make other's life easier?

jaho
  • 4,852
  • 6
  • 40
  • 66

1 Answers1

3

You can convert the BSTR object to char *, then convert it to QString. Here:

QString *getQStringFromBstr(BSTR bstrVal){
  char *p= const_cast<char *>(_com_util::ConvertBSTRToString(bstrVal));
  return new QString(p);
}

COM was designed to be Language-agnostic binary equalizer. Which means I could use a VB function in C++ and C++ function in, say, C#(with COM interop). This is the reason most of the strings and few functions were changed to language neutral strings IIRC.

Aniket Inge
  • 25,375
  • 5
  • 50
  • 78
  • Thanks. I still got a segfault but the conversion works. I've just now found in Microsoft's reference that the description of the method I've been using is "Do not use"... Still wonder about all the typedefs. – jaho Nov 05 '12 at 01:14
  • 1
    COM is a funny funny world :-) – Aniket Inge Nov 05 '12 at 01:15
  • Hmm, still a segfault with the following code and, this time, a working function: BSTR bstr = s->NuiDeviceConnectionId(); char* p = const_cast(_com_util::ConvertBSTRToString(bstr)); QString* qs = new QString(p); ui->lblDetails->setText(*qs); – jaho Nov 05 '12 at 01:20
  • it should be QString* qs = new QString(p); – Aniket Inge Nov 05 '12 at 01:29
  • It is. It's just not visible in comments (as well as ), but it's there. – jaho Nov 05 '12 at 01:33
  • the function I posted has nothing to do with Segfaults It does not access any data(and only converts) – Aniket Inge Nov 05 '12 at 01:34
  • see if bstr itself isn't NULL? – Aniket Inge Nov 05 '12 at 01:35
  • Ok, sorted. bstr wasn't NULL, but there was a null pointer few lines above which caused all the chaos. – jaho Nov 05 '12 at 01:47
  • Your proposed function can be simplified: no need to perform a `const_cast`, better return a `QString` instead of `QString*` (resource management!). And since `QString` can be constructed from a unicode string one can use `QString::fromUtf16` or `QString::fromWCharArray`. So in its simplest form we would end up with: `QString getQStringFromBstr(BSTR bstrVal) { return QString::fromWCharArray(bstrVal); }` – klaus triendl Nov 13 '13 at 14:27