Search code examples
c#c++qtcom

How to handle C# COM events in QT?


I have a simple C# COM visible library that looks like this:

namespace MyEventClassLibrary {

[Guid("0ab09e18-bf85-48c8-a45d-a0cebed77a5c")]
public interface ICalculator
{
    int Add(int Num1, int Num2);
}

[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
[Guid("9e09b634-8c1a-4926-83b2-f6f988595c85")]
public interface ICalculatorEvents
{
    [DispId(1)]
    void Completed(int Result);
}

[ClassInterface(ClassInterfaceType.None)]
[ComSourceInterfaces(typeof(ICalculatorEvents))]
[Guid("6cebc4db-2e8f-4e24-91a5-24ffdf97fc6a")]
public class Calculator : ICalculator
{
    [ComVisible(false)]
    public delegate void CompletedDelegate(int result);

    public event CompletedDelegate Completed;

    public int Add(int Num1, int Num2)
    {
        int Result = Num1 + Num2;
        if (Completed != null)
            Completed(Result);

        return Result;
    }
}}

I have it registered and I import the .TLB into QT with:

TYPELIBS = ..\MyEventClassLibrary\MyEventClassLibrary\bin\Debug\MyEventClassLibrary.tlb

and my mainwindow.cpp file looks like:

#include <QDebug>
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "myeventclasslibrary.h" 

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    MyEventClassLibrary::Calculator eventClass;
    connect(&eventClass, SIGNAL(Completed()), this, SLOT(test()));

    qDebug() << eventClass.Add(1,2);
}

void MainWindow::test()
{
    qDebug() << "Here";
}

MainWindow::~MainWindow()
{
    delete ui;
}

When I build the project in QT though, I get 40+ issues along the lines of:

MyEventClassLibrary.h:144: error: C2535: 'MyEventClassLibrary::CompletedDelegate::CompletedDelegate(void)': member function already defined or declared

and

MyEventClassLibrary.h:147: error: C2065: 'iface': undeclared identifier

The above has been resolved by adding [ComVisible(false)] to the delegate (see comments for more info)

When I run the code I get an error of:

QObject::connect: No such signal MyEventClassLibrary::Calculator::Completed()

My question is, how do you handle events/delegates in COM and QT?

As background info, the QT Documentation says:

If the COM object implements the IDispatch interface, the properties, methods and events of that object become available as Qt properties, slots and signals.

and I've used the following as resources and research:

Handle C# COM events in C++

how to put IDispatch* in managed code

How to fire c# COM events in c++?

and more; Please help!


Solution

  • This question had a 2-part question, with the goal of getting a C# COM-visible event to fire in QT:

    1. When I initially built the QT application, I was getting 40+ errors due to a delegate being visible. This was resolved by adding [ComVisible(false)] above the delegate declaration Thank you @HansPassant.

    2. When this was resolved, I tried to connect a SLOT to the COM SIGNAL, with QT saying it couldn't find the Completed event. This was resolved by matching up the function prototypes; Completed has a parameter of int, I was not including the int in the SLOT function. (derp)

    My original connect was:

    connect(&eventClass, SIGNAL(Completed()), this, SLOT(test()));
    

    it should have been:

    connect(&eventClass, SIGNAL(Completed(int)), this, SLOT(test(int)));
    

    Thanks!