C++ 从进程外COM服务器返回接口指针的正确方法是什么?

C++ 从进程外COM服务器返回接口指针的正确方法是什么?,c++,com,atl,C++,Com,Atl,我有一个out-of-proc-COM服务器,它有两个ATL-COM对象。object1公开一个接口,该接口在内部创建object2并以以下方式返回指向它的接口指针: HRESULT CObject1::CreateObject2(IObject2** pIobj2) { CComObject<Object2>* pObj = NULL; HRESULT hr = CComObject<Object2>::CreateInstance(&pObj

我有一个out-of-proc-COM服务器,它有两个ATL-COM对象。object1公开一个接口,该接口在内部创建object2并以以下方式返回指向它的接口指针:

HRESULT CObject1::CreateObject2(IObject2** pIobj2)
{
    CComObject<Object2>* pObj = NULL;

    HRESULT hr = CComObject<Object2>::CreateInstance(&pObj);

    hr = pObj->QueryInterface(IID_IObject2,(void**)pIobj2);

    //Some reason i need to store this pIobj2
    (*pIobj2)->AddRef();

    return hr;
}

我的要求是,客户端不应在
IObject1::CreateObject2()
之后的任何位置调用
IObject2
指针上的Release。要销毁object2,它应该调用
IOObject1::RemoveObject2()
。当我在RemoveObject2之后执行客户端时,object2不会被销毁,但是当我在RemoveObject2之后在客户端中调用IOObject2指针上的release时,object2被销毁。

进程外COM对象中的生命周期管理比进程内的复杂得多。例如,系统必须考虑到另一方可能会死亡(例如,如果客户端进程在没有发布的情况下死亡,则服务器应该清理分配给对象的资源)。为此,Microsoft有一个DCOM垃圾收集

实际上,在客户端(代理)和服务器(存根)上有两个COM对象。代理维护自己的引用计数,而您的代码会混淆此引用计数,因为您在服务器上释放了对象2的引用计数—这些信息不会到达客户端

我强烈建议您改变您的架构。首先,COM契约是释放对象的方式是使用释放方法。这就是合同,你的设计改变了它,这就是为什么你会对DCOM感到困惑

我认为更好的设计应该是:

  • 在Object2中保留对Object1的引用(例如,m_pobj1)
  • 没有Object1::RemoveObject2。如果需要做一些工作,可以使用私有(非COM)CleanupObject2
  • 实现Object2::FinalRelease(Object2的清理方法),并调用m_pobj1->cleanup[Object2(this)
  • 请记住,如果需要在obj1中保留指向obj2的指针,请确保这些是弱引用。也就是说,只是指针,而不添加引用计数

  • 客户端调用Object1::CreateObject2并获取对obj2的引用。完成后,它们将调用obj2->Release(),并将清除引用计数,然后调用obj1->CleanupObject2方法。

    这不正常。客户端上仍有一个代理具有非零引用计数。除了通过事件通知客户端它应该调用Release()之外,您无法以可靠的方式使此工作正常@HansPassant:谢谢你的回复。换句话说,客户端的refcount与服务器端的refcount不同,无论服务器是否在管理自己的refcount,客户端都必须调用release。请让我知道我的理解是否正确。再次感谢你。非常感谢。这有助于摆脱som这有助于我的理解。
    HRESULT CObject1::RemoveObject2(IObject2* pIobj2)
    {
        pIobj2->Release(); //This to compensate QI done in CreateObject2
    
        pIobj2->Release(); //This to compensate addref done to store in create
    }