0

问题:

在 COM 中,您偶尔会发现具有如下签名的函数

HRESULT STDMETHODCALLTYPE GetColorContexts( 
        UINT cCount,
        IWICColorContext **ppIColorContexts,
        UINT *pcActualCount)

这给我带来的问题是,它ppIColorContexts必须是一个已初始化IWICColorContext *. 我尝试引用 a Vectorof的第一个元素,ATL::CComPtr<IWICColorContext>但没有这样的运气,它不会触发()运算符,因此它抱怨类型不匹配。

尝试的解决方案:

  • vector<ATL::CComPtr<IWICColorContext>>由于类型不匹配而失败,如评论中所述,这还有其他问题,例如破坏 STL 容器的CComPtr重载。operator &似乎这在 C++11 中已修复,并包含在 VC2010 的 STL 中
  • BOOST_SCOPE_EXIT_ALL有效,但仍然意味着我正在手动管理 COM 对象的生命周期,这是我想摆脱的。

未尝试的解决方案:

  • 自定义数据结构——如果没有更优雅的解决方案,这可能是我必须做的,但至少它可以让我正确地利用破坏语义。
  • 在这个调用之后附加一个CComPtr- 我不喜欢这个解决方案,因为它给我留下了一段执行时间,如果出现问题,资源可能不会被释放。
  • std::unique_ptr<IWICColorContext[]>使用自定义删除器 - 我还没有完全探索这种可能性,但它可以确保 COM 对象总是被释放。
4

3 回答 3

2

我会通过将原始指针向量传递给函数,然后复制到另一个CComPtr.

std::vector<IWICColorContext *> vec(5, NULL);
UINT nActualCount = 0;
GetColorContexts(vec.size(), &vec[0], &nActualCount);
std::vector<CComPtr<IWICColorContext> > results(vec.begin(), vec.begin() + nActualCount);

唯一不幸的部分是CComPtr构造函数执行一个AddRef,所以你必须Release在原始指针丢失之前对它们进行相应的处理。

for (auto it = vec.begin(); it != vec.end(); ++it)
    if (*it != NULL)
        (*it)->Release();
vec.clear();
于 2013-09-18T21:01:42.240 回答
1

最终,igor tandetnik 在上面的评论中描述了该解决方案:

基本上在 VC2010+ATL::CComPtr中有一个sizeof与它们所代表的指针相同的指针(例如sizeof(ATL::CComPtr<IWICColorContext>) == sizeof(IWICColorContext*)),据我所知,这是因为它们没有虚函数,因此不需要 vTable。然而,这是非常危险的,因为它依赖于编译器实现细节。因此,以下工作:

std::vector<ATL::CComPtr<IWICColorContext> > > vec(5);
// CComPtrs are created and initialized here
GetColorContexts(vec.size(), &vec[0].m_T, ...);

Mark 提出了一个很好的观点,即上述解决方案完全依赖于编译器实现,这很危险。然而,仅ATL::CComPtrGetColorContexts调用后附加的解决方案也不可口,因为它不是异常安全的。

vector<IWICColorContext*>最终我的解决方案(今天早上测试)是从vector<CComPtr<IWICColorContext>>这个临时创建一个临时vector不增加引用计数并允许我保持异常安全。

于 2013-09-18T19:58:33.907 回答
-1

我认为你需要这样的东西:

long lSize = 0;
ptr->GetColorContexts(cCount, NULL, &lSize);//return required amount of contexts
IWICColorContext** ppColorContexts = NULL;
ppColorContexts = new IWICColorContext*[lSize];
ptr->GetColorContexts(cCount, ppColorContexts, &lSize);
//use something to wrap received raw interfaces with CComPtr - 
//for example use for loop to pass them to new container,
//which stores CComPtr<IWICColorContext>
于 2013-09-11T13:58:24.947 回答