来自书本ATL内部结构,我知道BSTR与OLECHAR*不同,BSTR有CComBSTR和CString。
根据MSDN为 BSTR 分配和释放内存 http://msdn.microsoft.com/en-us/library/vstudio/xda6xzx7%28v=vs.110%29.aspx,我知道调用者/被调用者的内存管理责任。
从 MSDN 中获取这一行,
HRESULT CMyWebBrowser::put_StatusText(BSTR bstr)
我还是不知道如何处理bstr
在我的实施中正确地执行。因为我对 BSTR 仍然有一个基本问题——我们应该治疗吗?bstr
作为值(如 int)或作为引用(如 int*),至少在 COM 接口边界上。
我想在我的实现中尽快将 BSTR 转换为 CString/CComBSTR。值或引用语义对于转换来说将是完全不同的情况。我深入研究了CComBSTR.Attach、CComBSTR.AssignBSTR等,但代码无法解决我的疑问。
MSDN CComBSTR.Attach 有一些代码片段,我觉得它是错误的,因为它不遵守为 BSTR 分配和释放内存 http://msdn.microsoft.com/en-us/library/vstudio/xda6xzx7%28v=vs.110%29.aspx。 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 包装器 http://en.wikipedia.org/wiki/Resource_Acquisition_Is_Initialization around raw BSTR
。所以请放心使用CComBSTR
而不是原始的BSTR
帮助编写异常安全的代码,这使得泄漏资源(即原始 BSTR)变得更加困难,等等。
If the BSTR
is an input参数,它就像一个const wchar_t*
(带有长度前缀,并且可能有一些NUL
s L'\0'
里面的字符)。如果BSTR
没有NUL
s 嵌入内部,您可以简单地将其传递给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
is an output参数,然后使用另一级间接传递,即BSTR*
。在这种情况下,您可以使用CComBSTR::Detach()
在你的方法中释放BSTR
安全地包裹在CComBSTR
,并将其所有权转移给调用者:
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
(封装在 RAII 类中,例如CComBSTR
) only 在边界处,并使用进行本地工作std::wstring
or CString
.
作为“奖励阅读”,请考虑Eric Lippert 的 BSTR 语义指南 http://blogs.msdn.com/b/ericlippert/archive/2003/09/12/52976.aspx.
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)