Qt version: 5.12.10
I wanted to interface with an application using the COM layer, this application was delivered with a .tlb file so I used Qt's dumpcpp to generate header and source file.
To use the generated class, I first get an IUnknown from windows ROT and then instantiate the classes I need from a class I used an interface.
My code looks like this :
Code instantiating my class:
//Initialize COM, load the ROT, get the monikers and for each monikers
//Check if the monikers name is the one we want
if (!wcsncmp(monikerDisplayName, appComIdentifier, wcslen(appComIdentifier)))
{
qDebug() << "Found app";
IUnknown *currentObject = nullptr;
if (rot->GetObject(currentMoniker, ¤tObject) == S_OK)
{
AppCommunication appCom(static_cast<app::IApplicationInterface *>(new QAxObject(currentObject)));
}
}
The AppCommunication class:
Header file:
class AppCommunication : public IAppCommunication
{
public:
AppCommunication(app::IApplicationInterface *applicationInterface);
~AppCommunication() override = default;
private:
app::appApplication appApplication;
app::appJob appJob;
};
cpp file:
AppCommunication::AppCommunication(app::IApplicationInterface *applicationInterface)
: appApplication(applicationInterface),
appJob(static_cast<app::IJobInterface *>(new QAxObject(appApplication.CreateJobObject())))
// ^
// |
// Segfault here
{
}
All the classes under the app namespace are the ones generated by the dumpcpp tool.
This works perfectly fine with the optimization flags -o0 or -o1 in the compiler but when I set -o2 or -o3 my program crashes.
From what I could trace this is the instantiation of the appJob (not the fetching of the JobInterface) that causes the crash.
I consider Qt's code and Qt's generated code to be robust/validated enough so I think this error must be me having an undefined behaviour. But I can not see what I did wrong here.
EDIT: I managed to find a way to avoid the issue. What I have found is that if I use a pointer instead of the class by itself it works fine:
Header file:
class AppCommunication : public IAppCommunication
{
public:
AppCommunication(app::IApplicationInterface *applicationInterface);
~AppCommunication() override = default;
private:
app::appApplication appApplication;
app::appJob *appJob;
};
cpp file:
AppCommunication::AppCommunication(app::IApplicationInterface *applicationInterface)
: appApplication(applicationInterface),
appJob(new app::appJob(static_cast<app::IJobInterface *>(new QAxObject(appApplication.CreateJobObject()))))
{
}
And this also work with a unique_ptr instead of the raw pointer so this is the route I will take.
I am more and more starting to think this is a MinGW because I can't see what could cause an issue like that...
The mistake was on me.
After getting the IUnknown * from the COM, we have to get a IDispatch * from it and then instantiate directly the classes:
//Initialize COM, load the ROT, get the monikers and for each monikers
//Check if the monikers name is the one we want
if (!wcsncmp(monikerDisplayName, appComIdentifier, wcslen(appComIdentifier)))
{
qDebug() << "Found app";
IUnknown *currentObject = nullptr;
if (rot->GetObject(currentMoniker, ¤tObject) == S_OK)
{
//Add the get dispatch part
IDispatch *currentObjectDispatch = nullptr;
HRESULT hr = currentObject->QueryInterface(IID_IDispatch, (void **)¤tObjectDispatch);
if (FAILED(hr))
{
return;
}
//Get the interface directly without static cast
AppCommunication appCom(new app::IApplicationInterface(currentObjectDispatch));
// Use the class instance with some method calls
}
}
And do the same on the class we retrieve in the ctor:
AppCommunication::AppCommunication(app::IApplicationInterface *applicationInterface)
: appApplication(applicationInterface),
appJob(new app::IJobInterface(appApplication.CreateJobObject()))
{
}