c# – 在不知道coclass的情况下发布COM接口
我有一个C#客户端,它使用本机C COM服务器DLL的接口.该DLL实现了4个接口.这4个接口由DLL中的4个coclasses实现.但是只有1个coclass暴露给客户端.接口2,3,4通过接口1中的一种方法返回给客户端.
C COM服务器: interface IFace1: IUnknown{ HRESULT CreateOtherInterface([in] REFIID iidFace,[out,iid_is(iidFace)] void** ppOut); }; coclass ClassIFace1 { [default] interface IFace1; }; C#客户端: ClassIFace1 Face1Obj = new ClassIFace1(); IFace1 Face1Ctrl = (IFace1)Face1Obj; IFace2 Face2Ctrl = null; IntPtr Face2IntPtr = new IntPtr(); Face1Ctrl.CreateOtherInterface(Face2Guid,out Face2IntPtr); Face2Ctrl = (IFace2)Mashal.PtrToStructure(Face2IntPtr); //Consume Face2Ctrl if(Face1Obj != null) { Marshal.ReleaseComObject(Face1Obj); } 由于IFace2,IFace3和IFace4不与IFace1共享相同的coclass,我怀疑Marshal.ReleaseComObject(Face1Obj)行只会破坏ClassIFace1对象而不会破坏ClassIFace2,ClassIFace3,ClassIFace4对象并导致内存泄漏.有什么方法可以解决这个问题吗?或者Marshal.ReleaseComObject(Face1Obj)实际上也会破坏其他COM对象? 解决方法
就像Hans说的那样,CreateOtherInterface看起来很奇怪.通常,您不需要自己创建它.您需要做的就是确保客户端可以访问所有四个coclass.然后,Activator.CreateInstance或本机CoCreateInstance将为您做正确的事情.另一种选择是暴露一个单一的coclass,并拥有支持所有四个接口的单个??coclass.
但是,由于你提到只有1个coclass暴露给客户端,我想象有一些奇怪的原因,客户端使用的TLB文件没有看到其他3个coclasses或其他3个coclass没有正确注册但是由一些专有方式的第一个coclass.我也假设您无法修改服务器端实现. 鉴于所有这些假设,这是我的答案.引用计数独立地保留在4个coclass中.因此,释放第一个coclass上的引用不会减少其他三个coclass中的引用计数. 还有一些事情你需要注意.您正在使用Marshal.ReleaseComObject(Face1Obj)来释放第一个coclass.你可以这样做,因为第一个coclass由Runtime Callable Wrapper(RCW)包装.就像Martin所说,即使你不调用Marshal.ReleaseComObject(),.NET运行时也会在发生garbabge收集时为你做. 但是,Face2Ctrl的获得方式不同.它不是由RCW包裹的.您将返回的指针直接视为结构.这对我来说听起来不对,因为您可能在内存对齐和数据编组方面存在问题.你想要做的可能是调用Marshal.GetObjectForIUnknown,它会为你返回一个RCW.获得RCW后,您可以调用Marshal.ReleaseComObject()以及时释放您的RCW. 如果CreateOtherInterface的实现类似于QueryInterface,它总是在返回的接口上添加AddRef,那么一旦完成Face2Obj,就应该在返回的接口上调用Marshal.Release. Marshal.ReleaseComObject()是不够的,因为它只释放了RCW添加的引用计数,但在这种情况下,你需要在IUnknown上调用一次更多. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |