gpt4 book ai didi

c++ - 我们应该将 COM 中的 BSTR 类型视为值还是引用?

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:55:15 26 4
gpt4 key购买 nike

ATL Internals 一书中,我知道 BSTR 不同于 OLECHAR*,BSTR 有 CComBSTR 和 CString。

根据 MSDN Allocating and Releasing Memory for a BSTR ,我知道调用者/被调用者的内存管理责任。

从 MSDN 中获取这一行,

HRESULT CMyWebBrowser::put_StatusText(BSTR bstr)

我仍然不知道如何在我的实现中正确处理 bstr。因为我仍然有一个关于 BSTR 的基本问题——我们应该将 bstr 视为一个值(如 int)还是一个引用(如 int*),至少在 COM 接口(interface)边界上。

我想在我的实现中尽快将 BSTR 转换为 CString/CComBSTR。对于转换,值或引用语义将完全不同。我已经深入研究了 CComBSTR.Attach、CComBSTR.AssignBSTR 等,但代码无法解决我的疑惑。

MSDN CComBSTR.Attach 有一些代码片段,我觉得这是错误的,因为它不遵守 Allocating and Releasing Memory for a BSTR . ATL Internals 表示 SetSysString 将“释放传入的原始 BSTR”,如果我使用它,它将违反 BSTR 参数约定,就像 CComBSTR.Attach。

总而言之,我想在实现中使用 CString 来处理原始 BSTR,但不知道正确的方法......我在我的项目中写了一些只是工作代码,但我总是感到紧张,因为我不知道不知道我说的对不对。

我来说说编码语言

HRESULT CMyWebBrowser::put_StatusText(BSTR bstr)
{
// What I do NOT know
CString str1; // 1. copy bstr (with embeded NUL)
CString str2; // 2. ref bstr

// What I know
CComBSTR cbstr1;
cbstr1.AssignBSTR(bstr); // 3. copy bstr
CComBSTR cbstr2;
cbstr2.Attach(bstr); // 4. ref bstr, do not copy

// What I do NOT know
// Should we copy or ref bstr ???
}

最佳答案

CComBSTR 只是一个 RAII wrapper围绕 raw BSTR。因此,请随意使用 CComBSTR 而不是原始 BSTR 来帮助编写异常安全的代码,这使得泄漏资源(即原始 BSTR)等更难。

如果 BSTR 是一个输入 参数,它就像一个 const wchar_t* (带有长度前缀,并且可能有一些 NULs L'\0' 里面的字符)。如果 BSTR 没有嵌入 NUL,您可以简单地将它传递给 CString 构造函数,这将进行深度复制它,您可以在本地使用您的 CString。对该 CString 的修改在原始 BSTR 上是不可见的。您也可以使用 std::wstring(注意 std::wstring 也可以处理嵌入的 NUL)。

void DoSomething(BSTR bstrInput)
{
std::wstring myString(bstrInput);
// ... work with std::wstring (or CString...) inside here
}

相反,如果 BSTR 是一个输出 参数,则使用另一个间接级别传递它,即 BSTR*。在这种情况下,您可以在您的方法中使用 CComBSTR::Detach() 来释放安全包装到 CComBSTR 中的 BSTR,并将其转移调用者的所有权:

HRESULT DoSomething( BSTR* pbstrOut )
{
// Check parameter pointer
if (pbstrOut == nullptr)
return E_POINTER;

// Guard code with try-catch, since exceptions can't cross COM module boundaries.
try
{
std::wstring someString;
// ... work with std::wstring (or CString...) inside here

// Build a BSTR from the ordinary string
CComBSTR bstr(someString.c_str());

// Return to caller ("move semantics", i.e. transfer ownership
// from current CComBSTR to the caller)
*pbstrOut = bstr.Detach();

// All right
return S_OK;
}
catch(const std::exception& e)
{
// Log exception message...
return E_FAIL;
}
catch(const CAtlException& e)
{
return e; // implicit cast to HRESULT
}
}

基本上,这个想法是使用 BSTR(包装在像 CComBSTR 这样的 RAII 类中)在边界,并使用 std::wstringCString 完成本地工作。

作为“奖励阅读”,请考虑 Eric Lippert's guide to BSTR semantics .

关于c++ - 我们应该将 COM 中的 BSTR 类型视为值还是引用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15441189/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com