【发布时间】:2021-06-17 04:15:55
【问题描述】:
我有一个用 C# 编写的 COM 对象,我在 C++ 中使用它,在我不得不向它添加事件之前,它可以正常工作。我尝试在这里查看无数教程、文档和问题,但奇怪的是,它们都不适合我的确切情况。
从我的代码中将事件源挂钩/取消挂钩到接收器的部分,我收到此错误:
Error C3731 incompatible event 'HRESULT EggplantClient::IEggplantClientEvents::Completed(void)' and handler 'HRESULT CReceiver::Completed(void)'; event source and event handler must have the same event type
我不知道这个“事件类型”是什么。我假设它是 CReceiver 类属性中的“com”部分:
[module(name = "EventReceiver")]
[event_receiver(com, true)]
class CReceiver {
...
至少这是我可以从Microsoft documentation 收集到的关于错误代码的信息。如果是这样,如何将 C# 事件源设置为相同类型?
我遇到的另一个非常奇怪的错误是:
Error C3702 ATL is required for COM events
这指向我定义class CReceiver 的行。我有与Microsoft documentation 中包含的完全相同的头文件来解决错误。我还从[module(name = "EventReceiver")] 行收到usage of ATL attributes is deprecated 的警告,我认为这些是相关的?
我已经被困在这个问题上好几天了。这是我第一次用 COM 做事,甚至 COM 服务器的基本实现也很困难,但试图让事件工作完全是一场噩梦。如果有人能以任何方式对此提供帮助,我将不胜感激,即使是指向显示在 C++ 客户端中的 C# COM 服务器上工作的事件的教程的链接也绰绰有余。以下是到目前为止我能够拼凑的相关部分。我使用this 作为客户端代码,服务器部分我什至找不到了,因为我已经浏览了很多页面。
C# COM 服务器,事件源
namespace EggplantClient
{
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
[Guid("C61C7C47-BB98-4DF3-BC61-7CA9430EDE7A")]
[ComVisible(true)]
public interface IEggplantClientEvents
{
[DispId(1)]
void Completed();
}
[Guid("0a805b99-756a-493c-96b7-063400f171ed")]
[ComVisible(true)]
[ClassInterface(ClassInterfaceType.None)]
[ComSourceInterfaces(typeof(IEggplantClientEvents))]
[ProgId("EggplantClient.CEggplantClient")]
public class CEggplantClient : IEggplantClient
{
[ComVisible(false)]public delegate void CompletedDelegate();
public event CompletedDelegate Completed;
...
C++ COM 客户端,事件接收者
#define _ATL_ATTRIBUTES 1
#include <atlbase.h>
#include <atlcom.h>
#include <atlctl.h>
#include <stdio.h>
int Flag = 0;
[module(name = "EventReceiver")]
[event_receiver(com, true)]
class CReceiver {
public:
HRESULT Completed() {
printf_s("Event received");
Flag = 1;
return S_OK;
}
void HookEvent(EggplantClient::IEggplantClient* pSource) {
__hook(&EggplantClient::IEggplantClientEvents::Completed, pSource, &CReceiver::Completed);
}
void UnhookEvent(EggplantClient::IEggplantClient* pSource) {
__unhook(&EggplantClient::IEggplantClientEvents::Completed, pSource, &CReceiver::Completed);
}
};
【问题讨论】: