我们将COM中的BSTR类型视为值或引用? [英] Shall we treat BSTR type in COM as value or reference?
问题描述
从书本 ATL Internals ,我知道BSTR与OLECHAR *不同,并且有用于BSTR的CComBSTR和CString。
From book ATL Internals, I knew BSTR is different from OLECHAR*, and there are CComBSTR and CString for BSTR.
根据MSDN 为BSTR分配和释放内存< a>,我知道调用者/被调用者的内存管理责任。
According MSDN Allocating and Releasing Memory for a BSTR, I knew memory management responsibility for caller/callee.
从MSDN获取此行,
code> HRESULT CMyWebBrowser :: put_StatusText(BSTR bstr)
HRESULT CMyWebBrowser::put_StatusText(BSTR bstr)
我还是不知道如何处理 bstr
。因为我还有一个BSTR的基本问题 - 我们应该把 bstr
作为一个值(如int)或者一个引用(如int *),至少在COM接口边界。
I still do not know how to handle bstr
properly in my implementation. Since I still have a basic question for BSTR -- should we treat bstr
as a value (like int) or as a reference (like int*), at least on COM interface boundary.
我想在我的实现中尽快将BSTR转换为CString / CComBSTR。值或引用语义将完全不同的情况下进行转换。我已经深入到CComBSTR.Attach,CComBSTR.AssignBSTR等,但是代码不能解决我的疑惑。
I want to convert BSTR as soon as possible to CString/CComBSTR in my implementation. Value or Reference semantic will be totally different case for the conversion. I've digged into CComBSTR.Attach, CComBSTR.AssignBSTR, etc. But the code cannot solve my doubts.
MSDN CComBSTR.Attach有一些代码剪辑,我觉得是错误的,因为它不服从为BSTR分配和释放内存。 ATL Internals说SetSysString将'释放原来的BSTR传入',如果我使用它,它将违反BSTR参数约定,就像CComBSTR.Attach。
MSDN CComBSTR.Attach has some code snip, I feel it is wrong since it is not obey Allocating and Releasing Memory for a BSTR. ATL Internals said SetSysString will 'free the original BSTR passed in', if I used it, it will violate BSTR argument convention, just like CComBSTR.Attach.
,我想使用CString处理原始BSTR在实现,但不知道正确的方式...我在项目中写了一些只是工作代码,但我总是感到紧张,因为我不知道我是否正确
All in all, I want to using CString to handle raw BSTR in implementation, but do not know the correct way...I've written some just work code in my projects, but I always feel nervous since I don't know whether I am correct.
让我谈谈编程语言
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包装器 raw BSTR
。因此,随时可以使用 CComBSTR
而不是原始 BSTR
来帮助编写异常安全的代码,泄漏资源(即原始BSTR)等。
CComBSTR
is just a RAII wrapper around raw BSTR
. So feel free to use CComBSTR
instead of raw BSTR
to help writing code that is exception-safe, that makes it harder to leak resources (i.e. the raw BSTR), etc.
如果 BSTR
是 / strong>参数,它就像一个 const wchar_t *
(带长度前缀,可能有一些 NUL
s L'\0'
字符里面)。如果 BSTR
没有嵌入 NUL
,您可以简单地将它传递给 CString
构造函数,它将对其进行深度复制,并且您可以在本地使用 CString
。对 CString
的修改将不会显示在原始的 BSTR
上。你也可以使用std :: wstring(并且注意 std :: wstring
也可以处理嵌入的 NUL
)。
If the BSTR
is an input parameter, it's just like a const wchar_t*
(with length prefixed, and potentially some NUL
s L'\0'
characters inside). If the BSTR
doesn't have NUL
s embedded inside, you can simply pass it to a CString
constructor, that will make a deep-copy of it, and you can locally work with your CString
. Modifications to that CString
won't be visible on the original BSTR
. You can use std::wstring as well (and note that std::wstring
can handle embedded NUL
s as well).
void DoSomething(BSTR bstrInput)
{
std::wstring myString(bstrInput);
// ... work with std::wstring (or CString...) inside here
}
$ b $相反,如果 BSTR
是输出参数,则使用另一级别的间接传递,即 BSTR *
。在这种情况下,您可以使用 CComBSTR :: Detach()
在您的方法中释放 BSTR
CComBSTR
,并将其所有权转让给调用者:
Instead, if the BSTR
is an output parameter, then it is passed using another level of indirection, i.e. BSTR*
. In this case, you can use CComBSTR::Detach()
inside your method to release the BSTR
safely wrapped into the CComBSTR
, and transfer its ownership to the caller:
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类中 em> ,并使用 std :: wstring
或 CString
进行本地工作。
Basically, the idea is to use BSTR
(wrapped in a RAII class like CComBSTR
) only at the boundary, and do the local work using std::wstring
or CString
.
As a "bouns reading", consider Eric Lippert's guide to BSTR semantics.
这篇关于我们将COM中的BSTR类型视为值或引用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!