将托管事件源连接到非托管事件接收器

时间:2009-07-06 20:06:34

标签: c# .net events com interop

我正在尝试用C#编写一个托管库,它将充当现有C ++事件接收器的事件源。我遇到的问题是,当非托管应用程序调用AtlAdvise来获取我的库的连接点映射时,它会收到错误“0x80040200”(CONNECT_E_NOCONNECTION) - 有一些关于该错误的MSDN文章与非托管相关< - > COM服务器中的非托管通信和无效的连接点映射,但没有关于托管COM服务器的信息。

我从非托管C ++服务器加载了idl,该服务器工作并获得了公开的事件列表,然后通过执行以下操作在我的代码中创建了相同的事件:

创建了包含我必须实现的接口的dll

[ComImport, InterfaceType(ComInterfaceType.InterfaceIsIDispatch), Guid("xxxxxx")]
public interface IMyInterface 
{
    ...
    methods here
    ...

创建了具有实现3个必需接口的类的dll

[Guid("xxxxxxx2")]
[ComSourceInterfaces(typeof(IMyInterface), typeof(IMyOtherInterface), typeof(IMyThirdInterface))]
public class DeviceTranslator : IDisposable, IMyInterface, IMyOtherInterface, IMyThirdInterface
{

在托管接口的命名空间中创建委托

namespace myNS.Interfaces
{
    public delegate void DistributeMessage([In] ref OLDMESSAGE Message);

并在实际的IMyInterface中创建事件

event DistributeMessage myDistributeMessage;

在我班上我实施了这个活动: 公共事件DistributeMessage myDistributeMessage;

我可以在构造函数中放置一个断点,看到dll被正确加载,但是当调用这段非托管代码时,我得到上面引用的错误:(pDistributeSink是一个强制转换为IUnknown *的CEventSink,以及GUID for IID_IDistributeEvent与IMyInterface相同的GUID)

hr = AtlAdvise(m_pUnknown, pDistributeSink, IID_IDistributeEvent, &m_dwConnectionPointCookie);

此时我完全摸不着头脑,不明白AtlAdvise还需要从CLR获取其连接点地图...

2 个答案:

答案 0 :(得分:4)

所以我等了5天,每天都在旋转我的车轮,但是在将它扔到这里之前无法解决这个问题,现在一小时后我发现了它......去了数字。

这是我必须做的事情(非常感谢codeproject

我继承了传出事件接口(IMyInterface)并在我的ClassInterface属性中定义它。我还在IMyInterface所在的命名空间中创建了委托,而不是DeviceTranslator类所在的命名空间。

事实证明我需要:

  • 只能在中定义 ClassInterface属性然后没有 覆盖其中的方法 接口

  • 在班级中创建代理 匹配的库命名空间 IMyInterface的方法签名 确切地说(与COM事件匹配 接收客户端方法)

  • 在课堂上创建活动 已命名的DeviceTranslator 与IMyInterface完全相同 方法

我在上面发布的链接中得到了很好的解释,并且它是第一个让它真正沉沦于一切如何真正运行以及必须在哪里创建的地方。

答案 1 :(得分:3)

我相信这是正确的代码项目链接:http://www.codeproject.com/KB/COM/cominterop.aspx#NetEvents