Mot*_*tti 11 c++ com atl safearray
我有一个COM函数应该通过LPSAFEARRAY*out参数返回一个SafeArray .该函数使用ATL的CComSafeArray模板类创建SafeArray .我的天真实现用于CComSafeArray<T>::Detach()将所有权从局部变量移动到输出参数:
void foo(LPSAFEARRAY* psa)
{
CComSafeArray<VARIANT> ret;
ret.Add(CComVariant(42));
*psa = ret.Detach();
}
int main()
{
CComSafeArray<VARIANT> sa;
foo(sa.GetSafeArrayPtr());
std::cout << sa[0].lVal << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
问题是CComSafeArray::Detach()执行一个Unlock操作,以便当SafeArray的新所有者(sa在这种情况下为main )被销毁时,锁定不为零并且Destroy无法解锁SafeArray E_UNEXPECTED(这导致内存泄漏,因为SafeArray不是解除分配).
通过COM方法边界将所有权转移到CComSafeArrays的正确方法是什么?
编辑:从单个答案到目前为止似乎错误是在客户端(main)而不是从服务器端(foo),但我发现很难相信这CComSafeArray不是为这个琐碎的用例设计的,必须是一种优雅的方法,可以将COMA方法中的SafeArray转换为CComSafeArray.
Amn*_*non 10
问题是您CComSafeArray直接设置接收的内部指针.使用该Attach()方法将现有附加SAFEARRAY到CComSafeArray:
LPSAFEARRAY ar;
foo(&ar);
CComSafeArray<VARIANT> sa;
sa.Attach(ar);
Run Code Online (Sandbox Code Playgroud)
只是为了确认标记的答案是正确的答案.RAII包装器不能跨COM边界工作.
发布的方法实现不正确,您不能假设调用者将提供有效的SAFEARRAY.只是[out]不是Automation中的有效属性,它必须是[out,retval]或[in,out].如果它是[out,retval],它看起来像,那么该方法必须从头开始创建一个新数组.如果它是[in,out],则该方法必须销毁传入的数组,如果它与预期的数组类型不匹配并创建一个新数组.