我有一个 .NET 库,需要为 COM 互操作公开它,包括一些异步操作。因此,我需要实现事件。从 C# 实现事件似乎很容易:
[ComVisible(true)]
[Guid("...")]
[ClassInterface(ClassInterfaceType.None)]
[ComSourceInterfaces(typeof(IClass1Event))]
public class Class1: IClass1
{
public delegate Int32 IntIntFunc(Int32 arg);
public event IntIntFunc Event;
public Int32 RaiseEvent(Int32 param)
{...}
}
[ComVisible(true)]
[Guid("...")]
public interface IClass1
{
Int32 RaiseEvent(Int32 param);
}
[ComVisible(true)]
[Guid("...")]
public interface IClass1Event
{
Int32 Event(Int32 param);
}
但是我在实现 C++ 事件接收器时遇到了问题。
我遇到的各种例子从普通的 IConnectionPoint::Advise
到单纯的“使用 VB”,但我在尝试实现它们时遇到了各种问题(不,我不能使用 VB) - 要么 ATL 拒绝为我实现 AddRef
,要么我无法用我的头脑掌握 VTable(不幸的是,我基本上精通 C 框架)。
我没有关于哪种框架更可取的信息,只有客户端是 C++。
所以我的问题是:将 .NET 事件公开给 C++ 的最简单方法是什么,因此,实现测试接收器的最简单方法是什么?
P.S.:我真的需要事件接口(interface)才能成为 IDispatch 吗?
最佳答案
如果您熟悉 COM,C++ 虚表非常简单。微软几乎将它们定义为相同的。也就是说,class IUnknown
的 MSVC++ vtable 是二进制的,与 interface IUnknown
的 COM 函数表相同。
现在,您似乎偶然发现了 IConnectionPoint::Advise
。这是可以理解的。它看起来像一个您必须实现的接口(interface),但事实并非如此。它是由事件源实现的接口(interface)。您可以使用它来告诉源要使用哪个接收器。
要查看会发生什么,将一个虚拟 IUnknown
对象传递给 IConnectionPoint::Advise
并在您的 IUnknown::QueryInterface
上放置一个断点。您将看到 IClass1Event
的事件源查询,当然是通过 GUID。现在,当您实现它时,您可以从 IUnknown::QueryInterface
返回它。
您不需要实现 IDispatch
接口(interface)。 .Net 可以没有;旧的 Visual Basic 6 需要它。那是因为 VB6 是弱类型的,需要后期绑定(bind)。
关于c# - 为 C++ 实现 .NET 事件的最简单方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9360196/