How do you specify "event type" in COM event source and handler?

  atl, c++, com, events

I have a COM object written in C# that I’m using in C++, and it worked without issues until I had to add events to it. I’ve tried looking at countless tutorials, documentation and questions here, but oddly enough none of them fit my exact situation.

From the parts in my code where I hook/unhook the event source to the receiver, I get this error:

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

I have no idea what this "event type" is. I assume it’s the "com" part in the CReceiver class attributes:

[module(name = "EventReceiver")]
[event_receiver(com, true)]
class CReceiver {
...

At least that’s what I can gather from the Microsoft documentation regarding the error code. If that is it, how can I set the C# event source to have the same type?

Another very weird error I’m having is this:

Error   C3702   ATL is required for COM events

This points to the line where I define class CReceiver. I have the exact same header files included as in the Microsoft documentation for the error. I also get a warning for usage of ATL attributes is deprecated from line [module(name = "EventReceiver")], I assume these are related?

I’ve been stuck on this for days. This is my first time doing stuff with COM, and even the basic implementation of the COM server was difficult, but trying to get events working has been a complete nightmare. I’d be incredibly grateful if anyone could help on this in any way, even a link to a tutorial that shows events working from a C# COM server in a C++ client would be more than enough. Below are the relevant parts of what I have been able to piece together so far. I used this for the client code, the server part I can’t even find anymore because I’ve waded through so many pages of this stuff.

C# COM server, the event source

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 client, the event receiver

#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);
    }
};

Source: Windows Questions C++

LEAVE A COMMENT