I have a console application with a QCoreApplication
running the event loop in main()
.
Here i have an Object, that is a derivative of QThread, with run()
implemented to do some testing.
I want the thread to start upon starting my application, so I called
QMetaObject::invokeMethod(&threadObj, &QThread::start, Qt::QueuedConnection);
return qapp.exec();
at the end of main()
.
Here is my Question: Why does this not compile?
Doing the same with QThread::quit
works fine, yet QThread::exit
does not.
I presume it has something to do with the arguments for start
and exit
?`
The Compiler Error looks like this btw:
d:\dev\project\project\main.cpp(49): error C2665: 'QMetaObject::invokeMethod': none of the 4 overloads could convert all the argument types
1>x:\hmi_qt5\qt\msvc2017_x86\debug\include\qtcore\qobjectdefs.h(448): note: could be 'bool QMetaObject::invokeMethod(QObject *,const char *,QGenericArgument,QGenericArgument,QGenericArgument,QGenericArgument,QGenericArgument,QGenericArgument,QGenericArgument,QGenericArgument,QGenericArgument,QGenericArgument)' (compiling source file main.cpp)
1>x:\hmi_qt5\qt\msvc2017_x86\debug\include\qtcore\qobjectdefs.h(431): note: or 'bool QMetaObject::invokeMethod(QObject *,const char *,Qt::ConnectionType,QGenericArgument,QGenericArgument,QGenericArgument,QGenericArgument,QGenericArgument,QGenericArgument,QGenericArgument,QGenericArgument,QGenericArgument,QGenericArgument)' (compiling source file main.cpp)
1>x:\hmi_qt5\qt\msvc2017_x86\debug\include\qtcore\qobjectdefs.h(414): note: or 'bool QMetaObject::invokeMethod(QObject *,const char *,QGenericReturnArgument,QGenericArgument,QGenericArgument,QGenericArgument,QGenericArgument,QGenericArgument,QGenericArgument,QGenericArgument,QGenericArgument,QGenericArgument,QGenericArgument)' (compiling source file main.cpp)
1>d:\dev\project\project\main.cpp(49): note: while trying to match the argument list '(threadObj*, void (__thiscall QThread::* )(QThread::Priority), Qt::ConnectionType)'
Thanks in Advance,
Bob
PS:
I do have a workaround for this, either by using functors or implementing a custom slot in threadObj
.
I asked this because I'm curious as to why this doesn't work, since I think the syntax is fine.
The problem is the existence of a parameter of QThread::start
, although defaulted, and Qt is broken in the aspect that the most important overloads of QMetaObject::invokeMethod
are defined with const char *member
as the 2nd parameter. So using one of those overloads you can use it directly:
#include <functional>
#include <QtWidgets/QApplication>
#include <QtWidgets/QtWidgets>
#include <QtWidgets/QMainWindow>
#include <QThread>
int main(int argc, char *argv[]) {
QThread threadObj;
QMetaObject::invokeMethod(&threadObj, "start", Qt::QueuedConnection);
QApplication this_application(argc, argv);
return this_application.exec();
}
Another solution would be
QMetaObject::invokeMethod(&threadObj, std::bind(&QThread::start,std::ref(threadObj),QThread::InheritPriority), Qt::QueuedConnection);
which is almost the same as a lambda, but IMHO clearer intention.