【问题标题】:How to convert BSTR to std::string in Visual Studio C++ 2010?如何在 Visual Studio C++ 2010 中将 BSTR 转换为 std::string?
【发布时间】:2012-11-23 09:55:55
【问题描述】:

我正在处理一个 COM dll。我希望将 BSTR 转换为 std::string 以传递给采用 const 引用参数的方法。

似乎使用 _com_util::ConvertBSTRToString() 来获取 BSTR 的 char* 等效项是一种合适的方法。但是,API 文档很少,实现可能存在错误:

http://msdn.microsoft.com/en-us/library/ewezf1f6(v=vs.100).aspx http://www.codeproject.com/Articles/1969/BUG-in-_com_util-ConvertStringToBSTR-and-_com_util

例子:

#include <comutil.h>
#include <string>

void Example(const std::string& Str) {}

int main()
{
    BSTR BStr = SysAllocString("Test");
    char* CharStr = _com_util::ConvertBSTRToString(BStr);
    if(CharStr != NULL)
    {
        std::string StdStr(CharStr);
        Example(StdStr);
        delete[] CharStr;
    }
    SysFreeString(BStr);
}

使用 ConvertBSTRToString() 的替代方法的优缺点是什么,最好基于标准方法和类?

【问题讨论】:

  • 垃圾进,垃圾出。您可以使用 WideCharToMultiByte() 编写自己的转换器,并在获得 1 兆字节的字符串时做一些更合理的事情。就像抛出异常一样。
  • 澄清一下,这是一个关于文档记录不佳的 MS comsupp-lib API 的问题吗?还是您在问自己如何做到这一点? (或两者兼而有之?)
  • @WhozCraig:我想两者都有,所以也许我应该把它们分成两个单独的问题,我会编辑这个以专注于我的目标而不是我的方法。
  • 请注意,在那个 codeproject 页面中,作者抱怨一个函数分配“两倍于 [it] 需要的内存”,因为他们分配了wcslen(str)*2。关于宽字符的宽度似乎存在误解。这篇文章应该与一些盐一起服用,可能是平时的两倍。

标签: c++ api visual-studio-2010 com


【解决方案1】:

你可以自己做。如果可能的话,我更喜欢转换成目标std::string。如果不是,请使用临时值覆盖。

// convert a BSTR to a std::string. 
std::string& BstrToStdString(const BSTR bstr, std::string& dst, int cp = CP_UTF8)
{
    if (!bstr)
    {
        // define NULL functionality. I just clear the target.
        dst.clear();
        return dst;
    }

    // request content length in single-chars through a terminating
    //  nullchar in the BSTR. note: BSTR's support imbedded nullchars,
    //  so this will only convert through the first nullchar.
    int res = WideCharToMultiByte(cp, 0, bstr, -1, NULL, 0, NULL, NULL);
    if (res > 0)
    {
        dst.resize(res);
        WideCharToMultiByte(cp, 0, bstr, -1, &dst[0], res, NULL, NULL);
    }
    else
    {    // no content. clear target
        dst.clear();
    }
    return dst;
}

// conversion with temp.
std::string BstrToStdString(BSTR bstr, int cp = CP_UTF8)
{
    std::string str;
    BstrToStdString(bstr, str, cp);
    return str;
}

调用为:

BSTR bstr = SysAllocString(L"Test Data String")
std::string str;

// convert directly into str-allocated buffer.
BstrToStdString(bstr, str);

// or by-temp-val conversion
std::string str2 = BstrToStdString(bstr);

// release BSTR when finished
SysFreeString(bstr);

反正就是这样。

【讨论】:

  • 感谢您,这正是我的情况所需要的。出于好奇(以及希望通过理解别人的代码来改进我的编程),如果可以问一下,有返回引用以及有输出引用参数的原因是什么?
  • 当然,既然我已经动了脑筋,它就可以根据方法调用(在我的示例中为Example(BstrToStdString(AString)))使用该方法。这种便利性似乎与使用临时作为“dst”输入(例如BstrToStdString(bstr,""))可能导致返回无效引用的风险进行了权衡。
  • @user1472525 您评论中的后一个示例BstrToStdString(bstr,"") 无效,因为输入参数必须是const std::string&amp; 类型,这不是出于明显的原因(毕竟,它是转换的目标)。所以无论如何你应该没问题。我经常通过 address 而不是引用传递这样的参数,以澄清其状态的参数外,但这样做 really 会引起大多数人的不满 -核心 C++ 民间 =P
  • WhozCraig*:感谢您的澄清,我没有考虑""const 本质。此外,感谢您避免指针/引用辩论,SO 已经有足够的 :-)。 * @ 功能这次似乎不起作用...
【解决方案2】:

简单的方法

BSTR => CStringW => CW2A => std::string.

【讨论】:

猜你喜欢
  • 2015-09-27
  • 2016-02-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多