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

标签 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,要么我无法用我的头脑掌握 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)。

More reading material.

关于c# - 为 C++ 实现 .NET 事件的最简单方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9360196/

相关文章:

c# - nant <version> 任务

c# - 如何从 GridView 在新选项卡中打开页面?

C# : Data collection to keep string?

c++ - 当绑定(bind)对象过期时,由 std::bind 创建的仿函数的行为是否定义明确?

javascript - .net MVC 中的 AJAX 请求适用于 Chrome,不适用于 Firefox 或 IE

.net - AutoFixture 与 NBuilder

c# - 如何判断我运行的是哪个 WCF 版本?

c# - 从流中更改图像大小

c++ - 如何将 vector 与 Boost.Test 进行比较?

c++ - 如何用两个 % 替换百分号 (%)?