BSTR到std :: string(std :: wstring),反之亦然


70

在C ++中使用COM时,字符串通常是BSTR数据类型。有人可以使用BSTR包装纸CComBSTR或MS的包装纸CString。但是因为我不能在MinGW编译器中使用ATL或MFC,是否有标准代码片段可以转换BSTRstd::string(或std::wstring),反之亦然?

是否还有一些非MS包装BSTR类似于CComBSTR

更新资料

感谢所有以任何方式帮助我的人!仅仅因为没有人解决过BSTR和之间的转换问题std::string,所以我想在此提供一些实现方法的线索。

以下是我用来分别转换BSTRstd::string和的函数:std::stringBSTR

std::string ConvertBSTRToMBS(BSTR bstr)
{
    int wslen = ::SysStringLen(bstr);
    return ConvertWCSToMBS((wchar_t*)bstr, wslen);
}

std::string ConvertWCSToMBS(const wchar_t* pstr, long wslen)
{
    int len = ::WideCharToMultiByte(CP_ACP, 0, pstr, wslen, NULL, 0, NULL, NULL);

    std::string dblstr(len, '\0');
    len = ::WideCharToMultiByte(CP_ACP, 0 /* no flags */,
                                pstr, wslen /* not necessary NULL-terminated */,
                                &dblstr[0], len,
                                NULL, NULL /* no default char */);

    return dblstr;
}

BSTR ConvertMBSToBSTR(const std::string& str)
{
    int wslen = ::MultiByteToWideChar(CP_ACP, 0 /* no flags */,
                                      str.data(), str.length(),
                                      NULL, 0);

    BSTR wsdata = ::SysAllocStringLen(NULL, wslen);
    ::MultiByteToWideChar(CP_ACP, 0 /* no flags */,
                          str.data(), str.length(),
                          wsdata, wslen);
    return wsdata;
}

2
您有使用Windowsstd::string而不是std::wstringWindows的原因吗?
ildjarn 2011年

是的,std::wstring也会顺利!问题已更新,感谢您对此发表评论!
ezpresso 2011年

为什么Windows上出现绞痛?
notbad.jpeg 2014年

1
@ notbad.jpeg:因为在VC ++中wchar_t是两个字节,而Windows的本机编码是USC-2(或UTF-16LE,具体取决于您询问的人)。因此,wstring保留字符串而不转换到Windows上的本机编码的自然方法是。
ildjarn 2014年

4
Windows的本机编码在Windows 2000中从UCS-2切换为UTF-16LE。对此没有任何“依赖于您询问的人”的信息。
雷米·勒博2015年

Answers:


98

BSTRstd::wstring

// given BSTR bs
assert(bs != nullptr);
std::wstring ws(bs, SysStringLen(bs));

 
std::wstringBSTR

// given std::wstring ws
assert(!ws.empty());
BSTR bs = SysAllocStringLen(ws.data(), ws.size());

文档参考:

  1. std::basic_string<typename CharT>::basic_string(const CharT*, size_type)
  2. std::basic_string<>::empty() const
  3. std::basic_string<>::data() const
  4. std::basic_string<>::size() const
  5. SysStringLen()
  6. SysAllocStringLen()

如果bs包含null,这不会失败吗?
Mooing Duck

2
@ildjam对不起,这是一个菜鸟问题,但是我开始在“转到定义”上进行操作BSTR(您将需要以admin身份运行VS),而且BSTR似乎不超过wchar_t*。另一方面,我还找到了Microsoft的文档,正如您所说,该文档表示此构造函数可以处理嵌入的空字符。BSTR如果构造函数只包含一个的指针,则该构造函数如何找到它的长度wchar_t
HerrKaputt 2014年

2
@HerrKaputt:因为BSTR是在一个特殊的堆上分配的,所以保留了分配的长度,并允许在给定BSTR的情况下查询该长度。
ildjarn 2014年

2
NULL是的有效状态BSTR,等效于空字符串。所以代码应该是std::wstring(bs ? bs : L"");
MM

1
关于语义没有混淆。ANULL BSTR在语义上与空值相同BSTR。那很容易映射到std::wstring。构造一个空值std::wstring是的唯一正确且明显的转换NULL BSTR
IInspectable '16

10

您也可以这样做

#include <comdef.h>

BSTR bs = SysAllocString("Hello");
std::wstring myString = _bstr_t(bs, false); // will take over ownership, so no need to free

或std :: string如果愿意的话

编辑:如果您的原始字符串包含多个嵌入式\ 0,则此方法将不起作用。


此答案不正确,如果您的字符串包含NULL字符,将给您不正确的结果。
慢性

在那种情况下,_bstr_t存在问题,尽管我从未遇到过任何问题。
AndersK '20

这只是一个问题,_bstr_t在目前为止,这是一个有点missleading。它只是隐式转换为wchar_t*。它从不声称它指向以空值结尾的字符串。就是在您将该值传递给std::wstring构造函数时,才创建问题。和一样错误std::wstring otherstring = something(); std::wstring mystring = otherstring.c_str()
慢性

我给出的示例没有错,但是如您所指出的那样,如果BSTR包含多个\ 0,它将无法正常工作。毫不奇怪,可能发生的最坏情况是字符串被截断。
AndersK

8

有一个名为的c ++类_bstr_t。它具有有用的方法和重载运算符的集合。

例如,您可以轻松地从“ a”const wchar_t *或“const char *公正”分配工作,_bstr_t bstr = L"My string"; 然后可以将其转换回“ doing” const wchar_t * s = bstr.operator const wchar_t *();。您甚至可以将其转换回常规char。const char * c = bstr.operator char *(); 然后可以使用const wchar_t *const char *初始化新的std::wstringoe std::string


2
好答案!std::string str = _bstr_t(theBSTR);简单!
PeteUK

4

只需将BSTR直接传递给wstring构造函数即可,它与wchar_t *兼容:

BSTR btest = SysAllocString(L"Test");
assert(btest != NULL);
std::wstring wtest(btest);
assert(0 == wcscmp(wtest.c_str(), btest));

将BSTR转换为std :: string首先需要转换为char *。因为BSTR存储utf-16编码的Unicode字符串,所以这是有损耗的。除非您要使用utf-8编码。您将在ICU库中找到用于执行此操作以及处理结果字符串的辅助方法。


10
即使所有包含空字符的字符串都被截断,BSTR并且std::wstring都可以正确存储它们。
JoeG 2011年

1
如果btest代表也失败null
Mooing Duck 2014年

3
gh,永远不要避免让程序意外崩溃的机会。
汉斯·帕桑
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.