2012-10-24 27 views
11

这可能是一个小菜COM的问题,但谷歌搜索引发更多的问题比提供的答案:使用C++“operator new”而不是CoCreateinstance创建COM对象是否安全?

是否可以安全地使用“operator new”而不是CoCreateInstance为本地COM实例?

我所做的:

  1. 我实现了IOperationsProgressDialog接口 http://msdn.microsoft.com/en-us/library/windows/desktop/bb775368(v=vs.85).aspx 通过使用公共的传承,从而也实现了IUnknown接口。

  2. 我通过“new RecyclerProgressCallback”创建了一个实例,并将其放入COM-Ptr进行生命周期管理。 “RecyclerProgressCallback”是我派生类的名称。

  3. 我用这个例子中IFileOperation :: SetProgressDialog http://msdn.microsoft.com/en-us/library/windows/desktop/bb775803(v=vs.85).aspx

摘要:我的方法“似乎”的工作,但我不相信它,周围还有只是太多令人不安的信息COM对象创建仅依赖于可观察行为。

是否有任何微妙的风险,谬误或其他问题?谢谢!

回答

5

我甚至把它们放在堆栈上。安德烈的答案(现在删除)错误地表明它是不安全的,因为你绕过COM引用计数。这是错误的推理。 COM不计算引用;它将责任交给你。在COM调用您的Release方法的最后一个界面后,您必须拨打deletefree()或您的语言使用的任何语言。之后的重要词是。不是,因为你没有义务立即这样做。

同样,CoCreateInstance是一个漫长的弯路,因为COM是语言中立的,不知道是否必须用mallocnew创建对象。你这样做,只是绕过整个COM逻辑。

+0

>只是绕过整个COM逻辑。 这就是我希望听到的!经过长时间的阅读,注册新的COM对象不仅在Visual C++ Express中很痛苦,而且会打破我的应用程序的“便携性”。 – Zenju

+0

那么,你仍然必须正确地实现'IUnknown',因为这是你承诺的IOperationsProgressDialog接口的一部分。例如。你的'IOperationsProgressDialog :: QueryInterface(IID_IUnknown)'必须成功等。 – MSalters

+0

是的,我做到了。这是很好的IUnknown是一个抽象的基类,所以我注意到编译器错误后,只实现了IOperationsProgressDialog。因此,整个过程只是普通的C++虚拟函数实现......这比我期望的COM更简单,这让我很怀疑。 – Zenju

1

这取决于你究竟在做什么。当你应该提供一个COM指针时,没有人会询问你是用COM API实现的,还是它可以是堆栈上的对象(前提是你可以设法确保它在所有引用被释放之前不会在堆栈上被销毁)。

所以答案是肯定的,你可以使用new,这样可以。但是,无论如何它应该是一个有效的COM接口,它应该以COM对象的方式实现引用计数和实现。

0

这将工作正常。这就是COM服务器通常在内部创建对象的方式(至少一个是用C++编写的)。从你的角度来看,RecyclerProgressCallback类只是一些C++代码。你可以把它当作你程序中的其他类。

这就是说,COM是一个微妙的陷阱雷区。我不能保证你不会遇到你的班级出现问题,但我可以向你保证,这些问题将与你使用新的操作员无关。

1

CoCreateInstance API将着眼于registry发现符合指定CLSID模块,加载和通过机制(这取决于你的代码是否为DLLEXE),它会调用一些功能来创建你的对象。因此,为了让您的代码能够使CoCreateInstance正常工作,您应该编写一个实现 COM接口的类并将其注册到注册表中,然后致电CoCreateInstance与您的代码做一些额外的工作,以至少做到您的可爱operator new那么当然是安全的。总的来说,在代码中调用operator newsource接口(只声明回调的接口)总是安全的,这也是首选方式。

-1

它通常不安全,不仅仅是因为引用计数,还因为编组:这个类可能有一个需要编组的线程模型。 CoCreateInstance将创建一个代理和存根(如果是这种情况),而new不会。

+0

这是不正确的。您将公开接口和COM对象,并且它们将由COM以相同的安全方式编组。 –

+0

否。如果类需要编组,则您从CoCreateInstance获得的是代理对象,而不是对象本身。 'new'永远不会发生这种情况。 – user1610015

+1

你无理由让事情变得凌乱。如果调用者需要在不同的公寓上课,他会从另一个线程'new'并让COM进行正常编组。 100%安全可行。如果主叫方因为某种原因需要“新”,并且他负责线程处理,“新”是绝对安全可靠的。 –

相关问题