client-side implementation of QMetaObject::invokeMethod(QObject *context, Functor function, Qt::ConnectionType type = Qt::AutoConnection)?
-
I'm working on a "retro-computing" project where I'd like to target Qt 5.8 at the latest.
Is there any possibility to provide a client-side equivalent implementation of
QMetaObject::invokeMethod(QObject *context, Functor function, Qt::ConnectionType type = Qt::AutoConnection)
, allowing me to do something likeQustom::invokeMethod(obj, [=](){ obj->method(a,b,c); }, Qt::BlockingQueuedConnection);
I suppose this variant should be cheaper than the old
invokeMethod(obj, "method", Qt::BlockingQueuedConnection, Q_ARG(?,a), Q_ARG(?, b), Q_ARG(?,c));
? -
I'm working on a "retro-computing" project where I'd like to target Qt 5.8 at the latest.
Is there any possibility to provide a client-side equivalent implementation of
QMetaObject::invokeMethod(QObject *context, Functor function, Qt::ConnectionType type = Qt::AutoConnection)
, allowing me to do something likeQustom::invokeMethod(obj, [=](){ obj->method(a,b,c); }, Qt::BlockingQueuedConnection);
I suppose this variant should be cheaper than the old
invokeMethod(obj, "method", Qt::BlockingQueuedConnection, Q_ARG(?,a), Q_ARG(?, b), Q_ARG(?,c));
?@RJV-B said in client-side implementation of QMetaObject::invokeMethod(QObject *context, Functor function, Qt::ConnectionType type = Qt::AutoConnection)?:
where I'd like to target Qt 5.8 at the latest
Depends on how far you want to go back. If you want your retro-project to support Qt4 versions, you cannot use lambdas.
Qustom
I like that name :)
-
No, I do plan to stick with Qt5, and may not need to go older than Qt 5.8 (the last to support OS X 10.9) and don't really want to go older than 5.6 .
Looking at the 5.10 sources I'd have to derive
QSlotObjectBase
class (looks like that might work) but also provide a customQFunctorSlotObject
class, to be used via aQFunctorSlotObjectWithNoArgs
template. That one has astatic void impl()
function, and the instance I'd create gets handed to theQMetaCallEvent
ctor, meaning I'd probably have to derive that class too in hope that gets me deep enough?I wonder if I didn't already try to go down this rabbit hole once for Qt 5.9 . I'd forgotten, but
invokeMethod
support for "functors" is actually among the tidbits that I ended up backporting to my patched Qt 5.9 . This time I'm not planning to "just patch Qt already" ;)Googling for a lib[std]c++ mechanism to execute a function on a specific thread I found this answer: https://stackoverflow.com/a/21653558/1460868 , suggesting in particular this bit of code:
void postToMainThread(std::function<void()> && fun) { QObject signalSource; QObject::connect(&signalSource, &QObject::destroyed, qApp, [fun(std::move(fun))](QObject*){ fun(); }); }
It appears to do the trick (at the cost of some additional overhead due to the temp. object). There's also
namespace detail { template <typename F> struct FEvent : public QEvent { using Fun = typename std::decay<F>::type; Fun fun; FEvent(Fun && fun) : QEvent(QEvent::None), fun(std::move(fun)) {} FEvent(const Fun & fun) : QEvent(QEvent::None), fun(fun) {} ~FEvent() { fun(); } }; } template <typename F> static void postToObject(F && fun, QObject * obj = qApp) { QCoreApplication::postEvent(obj, new detail::FEvent<F>(std::forward<F>(fun))); }
In both cases I'd need to verify if they do synchronous execution and, if not, figure out how to make them that.
EDIT: note to self: the 1st solution requires C++14, the second is C++11 compatible.