gpt4 book ai didi

c# - 在不知道 coclass 的情况下释放 COM 接口(interface)

转载 作者:行者123 更新时间:2023-11-30 12:32:23 25 4
gpt4 key购买 nike

我有一个 C# 客户端,它使用来自 native C++ COM 服务器 dll 的接口(interface)。 DLL 实现了 4 个接口(interface)。这4个接口(interface)由DLL中的4个coclasses实现。但是只有 1 个 coclass 暴露给客户端。接口(interface) 2、3、4 通过接口(interface) 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 对象?

最佳答案

就像汉斯说的,CreateOtherInterface看起来很奇怪。通常,您不需要自己创建它。您需要做的就是确保客户端可以访问所有四个组件类。然后,Activator.CreateInstance或 native CoCreateInstance会为你做正确的事。另一种选择是公开一个单独的组件类,并让该组件类支持所有四个接口(interface)。

但是,由于您提到只有 1 个 coclass 暴露给客户端,我想有一些奇怪的原因是客户端使用的 TLB 文件看不到其他 3 个 coclass,或者其他 3 个 coclass 没有正确注册但由第一个 coclass 以某些专有方式发现。我还假设您不能修改服务器端实现。

鉴于所有这些假设,这是我的答案。引用计数在 4 个 coclasses 中独立维护。因此,释放第一个组件类的引用不会减少其他三个组件类中的引用计数。

还有一些需要注意的地方。您正在使用 Marshal.ReleaseComObject(Face1Obj)发布第一个coclass。您可以这样做,因为第一个 coclass 由运行时可调用包装器 (RCW) 包装。正如 Martin 所说,即使您不调用 Marshal.ReleaseComObject() , .NET 运行时会在发生垃圾收集时为您完成。

但是,Face2Ctrl 的获取方式不同。它没有被 RCW 包裹。您将返回的指针直接视为结构。这对我来说听起来不对,因为您可能在内存对齐和数据编码方面遇到问题。你想做的可能是调用 Marshal.GetObjectForIUnknown这将为您返回一个 RCW。拿到 RCW 后,您可以调用 Marshal.ReleaseComObject()及时发布您的 RCW。

如果执行CreateOtherInterface就像QueryInterface , 总是 AddRef在返回的界面上,你应该调用Marshal.Release完成 Face2Obj 后在返回的界面上。 Marshal.ReleaseComObject()是不够的,因为它只是释放了 RCW 添加的引用计数,但在这种情况下,您需要对 IUnknown.Release 进行更多调用

关于c# - 在不知道 coclass 的情况下释放 COM 接口(interface),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11494416/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com