为C ++实现.NET事件的最简单方法

时间:2012-02-20 11:12:39

标签: c# c++ .net events com

我有一个.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对我来说,或者我不能用我的思想掌握VTables(不幸的是我基本上精通C框架)。 我没有关于什么框架更可取的信息,只有客户端是C ++。

所以我的问题是:将事件暴露给C ++最简单的方法是什么,因此,实现测试接收器的最简单方法是什么?

P.S。:我真的需要一个事件接口才能成为IDispatch吗?

1 个答案:

答案 0 :(得分:1)

如果你熟悉COM,那么C ++ vtable非常简单。微软几乎将它们定义为相同。也就是说,class IUnknown的MSVC ++ vtable是二进制文件,与interface IUnknown的COM函数表相同。

现在,你似乎偶然发现IConnectionPoint::Advise。这是可以理解的。它看起来像你必须实现的接口,但事实并非如此。它是由事件源实现的接口。您可以使用它来告诉源使用什么接收器。

要查看会发生什么,请将虚拟IUnknown对象传递给IConnectionPoint::Advise并在IUnknown::QueryInterface上放置一个断点。您当然会看到GUID的IClass1Event事件源查询。现在,当您实现它时,您可以从IUnknown::QueryInterface返回它。

您不需要实现IDispatch接口。 .Net可以不用;它是需要它的旧Visual Basic 6。那是因为VB6是弱类型的,需要后期绑定。

More reading material.