1

我有一个 COM 功能:

GetData(SAFEARRAY ** pRetVal)

并遵循遗留代码:

CComSafeArray<double> saDataArray;
hr = pmyInterface->GetData(&saDataArray.m_psa);
SafeArrayLock(saDataArray);

我怀疑手动管理锁是否好。m_psa当返回为NULLby时,该代码会崩溃GetData吗?

下面的代码怎么样?那个更好吗?

LPSAFEARRAY psa;
CComSafeArray<double> saDataArray;
hr = pmyInterface->GetData(&psa);
saDataArray.Attach(psa);

编辑: 我测试了上面的两个代码。有一个区别。如果GetData返回NULL,则直接AttachNULL检查将调用异常。第一个版本将返回一个E_INVALIDARG. 我的问题仍然存在,您是否更喜欢更高版本,因为它使用 SafeArray 对象来维护计数,而不是混合它?

EDIT2: 如果出于某种原因我选择了第一个版本,可以忽略E_INVALIDARG返回值吗?当某些代码稍后使用它时,这会有什么副作用saDataArray吗?

4

1 回答 1

2

你写了:

SafeArray * psa;
CComSafeArray<double> saDataArray;
hr = pmyInterface->GetData(&psa);
saDataArray.Attach(psa);

但我认为实际的代码应该是:

LPSAFEARRAY psa; // not "SafeArray *"
hr = pmyInterface->GetData(&psa);
CComSafeArray<double> saDataArray;
saDataArray.Attach(psa);

有关详细信息,请参阅此问题

编辑:根据您的问题编辑更新答案。

我真的不喜欢你的第一个代码:

CComSafeArray<double> saDataArray;
hr = pmyInterface->GetData(&saDataArray.m_psa);
SafeArrayLock(saDataArray); // <--- Explicit lock on a CComSafeArray-wrapped array

事实上,一旦将原始SAFEARRAY数据提供给 C++ RAII 包装器 ( CComSafeArray),从那时起,我将只使用此包装器及其方法来操作数组。
如果您想对数组进行“手动”处理,只需.Detach()使用 C++ 包装器,并使用 Win32 API 函数调用。但是将两者混合并不是质量好的代码,IMO。

请注意,第二种方法不同,因为您首先使用 raw SAFEARRAY,使GetData()方法填充它,然后将.Attach()其传递给CComSafeArrayC++ RAII 包装器,将所有权(“移动语义”)转移到该包装器。然后就可以使用包装器方法来操作数组了。

此外,在生产质量代码中,我不会忽略 error HRESULT

于 2013-04-22T09:39:27.320 回答