我对用于C ++编程的COM智能指针类的选择感到困惑:
我知道三四:
CCOMPtr
_com_ptr_t
TComInterface
(因为我正在使用C ++ Builder 2009)CCOMQIPtr
,(我之前忘记了)我已经读过前两个的错误与异常处理差异,但TComInterface
似乎完全没有记录。从我能找到的东西来看,前两个似乎都有问题或“出乎意料”的行为。
理想情况下,我想要一些干净而现代的C ++,但据我所知,boost::com
并不存在......
我需要控制其他供应商的应用程序。它们通过TLB文件提供COM接口。
答案 0 :(得分:4)
如果您正在使用类型库导入内容,它将生成基于_com_ptr_t
和相关COM支持类的代码。如果您只是使用这些库中的东西,请继续使用它们。
如果您正在编写基于ATL的代码,请使用CCOMPtr
和其他基于ATL的类。
如果你需要混合搭配这两种类型,事情可能变得很难看,但是你应该对这两种类型感到满意,并使用那些对你当时所做的事情最有意义的事情。
好消息是你拥有所有这些东西的来源,所以你不必只依赖于文档(自.NET出现以来一直没有得到太多关注)。
答案 1 :(得分:2)
由于你要求“干净和现代”的C ++风格,并以提升为例,我还要再提两个:std/boost::shared_ptr
和boost::intrusive_ptr
。 intrusive_ptr显然是更自然的选择,因为COM对象具有侵入式引用计数机制。 shared_ptr也可以,你只需要使用一个调用IUnknown::Release()
的自定义删除器,以及一个执行IUnknown::AddRef()
并返回智能指针的小对象生成器函数。
我通常选择intrusive_ptr
,所以我将更详细地解释一下。首先,当然,必须为所有IUnknown
实现intrusive_ptr_add_ref和intrusive_ptr_release。 intrusive_ptr
构造函数已经有一个方便的功能,可以跳过添加另一个引用,因为很多COM函数都会为你执行AddRef()
。
现在这种方法存在一个问题:intrusive_ptr不像其他一些COM指针那样暴露其底层裸指针。这是一个问题,因为创建COM对象的常用方法是将指针传递给指向另一个对象中某个创建函数的指针。由于您无法将intrusive_ptr传递给这些函数,因此最终会出现用于初始化intrusive_ptr的笨拙的临时裸指针。这不是很优雅,更不用说异常安全了(如果您需要使用COM代码,这自然不会抛出异常。我将COM错误转换为异常。)
所以我在这里做的是使用另一个工具函数来转换一个函数,该函数接受任何com函数并返回一个可调用的函数,其中任何指针指向T的指针都可以是或者对它的引用intrusive_ptr。其他任何东西就像“输入功能”。这些函数然后执行T **和intrusive_ptr&之间的所有转换。为了我。例如,HRESULT CreateBuffer(IBuffer** bufferOut, int size)
变为可以使用签名HRESULT CreateBuffer(instrusive_ptr<IBuffer>& bufferOut, int size)
进行调用。除非你有代码生成器,耐心,或者我认为是可变参数模板,否则为“所有”arities编写它们有点乏味。但是一旦你拥有它们,它实际上使得与COM合作非常好。
答案 2 :(得分:1)
我使用了前两个,CComPtr和_com_ptr_t。
听起来你已经读过有关错误和异常处理的区别,所以选择你最喜欢的那个,或者最符合代码中其余错误处理的那个。
答案 3 :(得分:0)
如kenny
所述,您可以使用CComPtr
来管理指向COM接口的指针。这个类有详细记录(参见msdn)并使用自动引用计数,我想,你想要的是什么。
OTOH,Rob
问题很重要:你真的使用COM接口吗?对于指针,您可以使用STL
或boost
库中的智能指针,这些指针无论如何都比CComPtr
更好。