为了账号安全,请及时绑定邮箱和手机立即绑定

将COM事件从C#触发到C ++的正确方法是什么

将COM事件从C#触发到C ++的正确方法是什么

C++
慕工程0101907 2021-05-11 17:49:45
我们有一个项目,其中包含许多C ++(使用ATL),VB6和最近的C#遗留代码。我们最近将组件从C ++移植到了C#,该事件触发由C ++,VB6和C#中的组件处理的事件。从理论上讲,一切正常,但是触发事件会生成许多System.NotImplementedExceptions。我已经修改了触发事件的代码,以便它分别调用每个事件处理程序,这样一个对象的异常不会阻止它在下一个对象中调用事件处理程序。if ( GeneratedChannelChange != null ){  // Invoke each handler separately, so that an exception in one invokation does not prevent us calling the next one.  foreach ( GeneratedChannelChangeEventHandler del in GeneratedChannelChange.GetInvocationList() )  {    try    {      del.Invoke ( GenChan, ChangeMask ) ;    }    catch  ( Exception ) {}  }}实际上,由ATL向导生成的原始C ++代码也忽略了invoke函数返回的错误。这似乎工作正常,但是我对它产生的大量异常不满意。在调试器中运行时,这也会降低性能。我认为只有在C ++类中处理事件时才会引发异常。这是使用ATL类IDispEventSimpleImpl实现的。我发现的是,IDispEventSimpleImpl没有实现功能GetIDsOfNames。肯定会调用此函数,并且它将返回E_NOTIMPL。可能是新的C#代码正在调用函数GetIDsOfNames,而旧的C ++代码没有吗?如果是这样,是否有任何简单的方法可以在使用IDispEventSimpleImpl的类中实现功能GetIDsOfNames?如果我的分析是错误的,是否有“正确”的方法在C#(作为事件源)和C ++(作为事件接收器)中实现事件逻辑?
查看完整描述

1 回答

?
偶然的你

TA贡献1841条经验 获得超3个赞

我想,我已经解决了这一问题,通过更换IDispEventSimpleImpl的与IDispEventImpl的。


这或多或少是一个即插即用的替代品,但是它确实需要引用类型库。


ATL类继承了多个基类,包括一个定义为WorkspaceEventSink的基类。


class ATL_NO_VTABLE CImportChannels :

  ...

  public WorkspaceEventSink,

  ...

{

   ...

}

先前定义为


typedef IDispEventSimpleImpl< 42, CImportChannels, &DIID_ICs3WorkspaceEvents>        WorkspaceEventSink ;

我已将定义更改为


typedef IDispEventImpl< 42, CImportChannels, &DIID_ICs3WorkspaceEvents, &LIBID_McAnalEventsNET, 1, 0 >        WorkspaceEventSink ;

除了将IDispEventSimpleImpl更改为IDispEventImpl外,我还添加了类型库的GUID及其主要版本号和次要版本号。


最初,我尝试不使用主要版本号和次要版本号,但这导致了类型库未注册的异常。


无需进行其他更改(例如对接收器映射进行更改)。


查看完整回答
反对 回复 2021-05-23
  • 1 回答
  • 0 关注
  • 298 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信