From 4c571032f8763c55526a3d9f6bcb8e1336766bd9 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Thu, 16 May 2019 09:28:55 +0200 Subject: [PATCH] Add support for slots to receive the raw void ** arguments array This is currently being used by dbus und our state machine framework, and supported by hand editing moc generated code. Get rid of that hack, and instead add support to moc to forward the raw arguments array to the slot. Change-Id: I0e36626f91eb01041464e6d931dc1d4660de91d2 Reviewed-by: Simon Hausmann --- src/corelib/kernel/qmetaobject.cpp | 15 +++ src/corelib/kernel/qobjectdefs.h | 4 + .../statemachine/qsignaleventgenerator_p.h | 7 +- src/corelib/statemachine/qstatemachine.cpp | 92 +------------- src/dbus/qdbusabstractadaptor.cpp | 118 +----------------- src/dbus/qdbusabstractadaptor_p.h | 9 +- src/tools/moc/generator.cpp | 28 +++-- src/tools/moc/moc.cpp | 5 + src/tools/moc/moc.h | 1 + 9 files changed, 52 insertions(+), 227 deletions(-) diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp index 5cb30a74ac..a8e8866339 100644 --- a/src/corelib/kernel/qmetaobject.cpp +++ b/src/corelib/kernel/qmetaobject.cpp @@ -3654,6 +3654,21 @@ const char* QMetaClassInfo::value() const return rawStringData(mobj, mobj->d.data[handle + 1]); } +/*! + \class QMethodRawArguments + \internal + + A wrapper class for the void ** arguments array used by the meta + object system. If a slot uses a single argument of this type, + the meta object system will pass the raw arguments array directly + to the slot and set the arguments count in the slot description to + zero, so that any signal can connect to it. + + This is used internally to implement signal relay functionality in + our state machine and dbus. +*/ + + /*! \macro QGenericArgument Q_ARG(Type, const Type &value) \relates QMetaObject diff --git a/src/corelib/kernel/qobjectdefs.h b/src/corelib/kernel/qobjectdefs.h index dc2d832fe5..9f654b0318 100644 --- a/src/corelib/kernel/qobjectdefs.h +++ b/src/corelib/kernel/qobjectdefs.h @@ -285,6 +285,10 @@ class QMetaEnum; class QMetaProperty; class QMetaClassInfo; +struct QMethodRawArguments +{ + void **arguments; +}; class Q_CORE_EXPORT QGenericArgument { diff --git a/src/corelib/statemachine/qsignaleventgenerator_p.h b/src/corelib/statemachine/qsignaleventgenerator_p.h index 72592b8731..a9d5b96920 100644 --- a/src/corelib/statemachine/qsignaleventgenerator_p.h +++ b/src/corelib/statemachine/qsignaleventgenerator_p.h @@ -62,13 +62,12 @@ class QStateMachine; class QSignalEventGenerator : public QObject { - Q_OBJECT_FAKE + Q_OBJECT public: QSignalEventGenerator(QStateMachine *parent); -private: -// slots - void execute(void **_a); +private Q_SLOTS: + void execute(QMethodRawArguments a); private: Q_DISABLE_COPY_MOVE(QSignalEventGenerator) diff --git a/src/corelib/statemachine/qstatemachine.cpp b/src/corelib/statemachine/qstatemachine.cpp index 945e36968f..0ed92514f9 100644 --- a/src/corelib/statemachine/qstatemachine.cpp +++ b/src/corelib/statemachine/qstatemachine.cpp @@ -3045,102 +3045,14 @@ void QStateMachine::removeDefaultAnimation(QAbstractAnimation *animation) #endif // animation - -// Begin moc-generated code -- modify carefully (check "HAND EDIT" parts)! -struct qt_meta_stringdata_QSignalEventGenerator_t { - QByteArrayData data[3]; - char stringdata[32]; -}; -#define QT_MOC_LITERAL(idx, ofs, len) \ - Q_STATIC_BYTE_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(len, \ - offsetof(qt_meta_stringdata_QSignalEventGenerator_t, stringdata) + ofs \ - - idx * sizeof(QByteArrayData) \ - ) -static const qt_meta_stringdata_QSignalEventGenerator_t qt_meta_stringdata_QSignalEventGenerator = { - { -QT_MOC_LITERAL(0, 0, 21), -QT_MOC_LITERAL(1, 22, 7), -QT_MOC_LITERAL(2, 30, 0) - }, - "QSignalEventGenerator\0execute\0\0" -}; -#undef QT_MOC_LITERAL - -static const uint qt_meta_data_QSignalEventGenerator[] = { - - // content: - 7, // revision - 0, // classname - 0, 0, // classinfo - 1, 14, // methods - 0, 0, // properties - 0, 0, // enums/sets - 0, 0, // constructors - 0, // flags - 0, // signalCount - - // slots: name, argc, parameters, tag, flags - 1, 0, 19, 2, 0x0a, - - // slots: parameters - QMetaType::Void, - - 0 // eod -}; - -void QSignalEventGenerator::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a) -{ - if (_c == QMetaObject::InvokeMetaMethod) { - Q_ASSERT(staticMetaObject.cast(_o)); - QSignalEventGenerator *_t = static_cast(_o); - switch (_id) { - case 0: _t->execute(_a); break; // HAND EDIT: add the _a parameter - default: ; - } - } - Q_UNUSED(_a); -} - -const QMetaObject QSignalEventGenerator::staticMetaObject = { - { &QObject::staticMetaObject, qt_meta_stringdata_QSignalEventGenerator.data, - qt_meta_data_QSignalEventGenerator, qt_static_metacall, 0, 0 } -}; - -const QMetaObject *QSignalEventGenerator::metaObject() const -{ - return &staticMetaObject; -} - -void *QSignalEventGenerator::qt_metacast(const char *_clname) -{ - if (!_clname) return 0; - if (!strcmp(_clname, qt_meta_stringdata_QSignalEventGenerator.stringdata)) - return static_cast(const_cast< QSignalEventGenerator*>(this)); - return QObject::qt_metacast(_clname); -} - -int QSignalEventGenerator::qt_metacall(QMetaObject::Call _c, int _id, void **_a) -{ - _id = QObject::qt_metacall(_c, _id, _a); - if (_id < 0) - return _id; - if (_c == QMetaObject::InvokeMetaMethod) { - if (_id < 1) - qt_static_metacall(this, _c, _id, _a); - _id -= 1; - } - return _id; -} -// End moc-generated code - -void QSignalEventGenerator::execute(void **_a) +void QSignalEventGenerator::execute(QMethodRawArguments a) { auto machinePrivate = QStateMachinePrivate::get(qobject_cast(parent())); if (machinePrivate->state != QStateMachinePrivate::Running) return; int signalIndex = senderSignalIndex(); Q_ASSERT(signalIndex != -1); - machinePrivate->handleTransitionSignal(sender(), signalIndex, _a); + machinePrivate->handleTransitionSignal(sender(), signalIndex, a.arguments); } QSignalEventGenerator::QSignalEventGenerator(QStateMachine *parent) diff --git a/src/dbus/qdbusabstractadaptor.cpp b/src/dbus/qdbusabstractadaptor.cpp index 993607a643..b7b291551d 100644 --- a/src/dbus/qdbusabstractadaptor.cpp +++ b/src/dbus/qdbusabstractadaptor.cpp @@ -276,11 +276,11 @@ void QDBusAdaptorConnector::polish() std::sort(adaptors.begin(), adaptors.end()); } -void QDBusAdaptorConnector::relaySlot(void **argv) +void QDBusAdaptorConnector::relaySlot(QMethodRawArguments argv) { QObject *sndr = sender(); if (Q_LIKELY(sndr)) { - relay(sndr, senderSignalIndex(), argv); + relay(sndr, senderSignalIndex(), argv.arguments); } else { qWarning("QtDBus: cannot relay signals from parent %s(%p \"%s\") unless they are emitted in the object's thread %s(%p \"%s\"). " "Current thread is %s(%p \"%s\").", @@ -333,120 +333,6 @@ void QDBusAdaptorConnector::relay(QObject *senderObj, int lastSignalIdx, void ** emit relaySignal(realObject, senderMetaObject, lastSignalIdx, args); } -// our Meta Object -// modify carefully: this has been hand-edited! -// the relaySlot slot gets called with the void** array - -struct qt_meta_stringdata_QDBusAdaptorConnector_t { - QByteArrayData data[10]; - char stringdata[96]; -}; -#define QT_MOC_LITERAL(idx, ofs, len) \ - Q_STATIC_BYTE_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(len, \ - offsetof(qt_meta_stringdata_QDBusAdaptorConnector_t, stringdata) + ofs \ - - idx * sizeof(QByteArrayData) \ - ) -static const qt_meta_stringdata_QDBusAdaptorConnector_t qt_meta_stringdata_QDBusAdaptorConnector = { - { -QT_MOC_LITERAL(0, 0, 21), -QT_MOC_LITERAL(1, 22, 11), -QT_MOC_LITERAL(2, 34, 0), -QT_MOC_LITERAL(3, 35, 3), -QT_MOC_LITERAL(4, 39, 18), -QT_MOC_LITERAL(5, 58, 10), -QT_MOC_LITERAL(6, 69, 3), -QT_MOC_LITERAL(7, 73, 4), -QT_MOC_LITERAL(8, 78, 9), -QT_MOC_LITERAL(9, 88, 6) - }, - "QDBusAdaptorConnector\0relaySignal\0\0" - "obj\0const QMetaObject*\0metaObject\0sid\0" - "args\0relaySlot\0polish\0" -}; -#undef QT_MOC_LITERAL - -static const uint qt_meta_data_QDBusAdaptorConnector[] = { - - // content: - 7, // revision - 0, // classname - 0, 0, // classinfo - 3, 14, // methods - 0, 0, // properties - 0, 0, // enums/sets - 0, 0, // constructors - 0, // flags - 1, // signalCount - - // signals: name, argc, parameters, tag, flags - 1, 4, 29, 2, 0x05, - - // slots: name, argc, parameters, tag, flags - 8, 0, 38, 2, 0x0a, - 9, 0, 39, 2, 0x0a, - - // signals: parameters - QMetaType::Void, QMetaType::QObjectStar, 0x80000000 | 4, QMetaType::Int, QMetaType::QVariantList, 3, 5, 6, 7, - - // slots: parameters - QMetaType::Void, - QMetaType::Void, - - 0 // eod -}; - -void QDBusAdaptorConnector::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a) -{ - if (_c == QMetaObject::InvokeMetaMethod) { - Q_ASSERT(staticMetaObject.cast(_o)); - QDBusAdaptorConnector *_t = static_cast(_o); - switch (_id) { - case 0: _t->relaySignal((*reinterpret_cast< QObject*(*)>(_a[1])),(*reinterpret_cast< const QMetaObject*(*)>(_a[2])),(*reinterpret_cast< int(*)>(_a[3])),(*reinterpret_cast< const QVariantList(*)>(_a[4]))); break; - case 1: _t->relaySlot(_a); break; // HAND EDIT: add the _a parameter - case 2: _t->polish(); break; - default: ; - } - } -} - -const QMetaObject QDBusAdaptorConnector::staticMetaObject = { - { &QObject::staticMetaObject, qt_meta_stringdata_QDBusAdaptorConnector.data, - qt_meta_data_QDBusAdaptorConnector, qt_static_metacall, 0, 0 } -}; - -const QMetaObject *QDBusAdaptorConnector::metaObject() const -{ - return &staticMetaObject; -} - -void *QDBusAdaptorConnector::qt_metacast(const char *_clname) -{ - if (!_clname) return 0; - if (!strcmp(_clname, qt_meta_stringdata_QDBusAdaptorConnector.stringdata)) - return static_cast(const_cast< QDBusAdaptorConnector*>(this)); - return QObject::qt_metacast(_clname); -} - -int QDBusAdaptorConnector::qt_metacall(QMetaObject::Call _c, int _id, void **_a) -{ - _id = QObject::qt_metacall(_c, _id, _a); - if (_id < 0) - return _id; - if (_c == QMetaObject::InvokeMetaMethod) { - if (_id < 3) - qt_static_metacall(this, _c, _id, _a); - _id -= 3; - } - return _id; -} - -// SIGNAL 0 -void QDBusAdaptorConnector::relaySignal(QObject * _t1, const QMetaObject * _t2, int _t3, const QVariantList & _t4) -{ - void *_a[] = { 0, const_cast(reinterpret_cast(&_t1)), const_cast(reinterpret_cast(&_t2)), const_cast(reinterpret_cast(&_t3)), const_cast(reinterpret_cast(&_t4)) }; - QMetaObject::activate(this, &staticMetaObject, 0, _a); -} - QT_END_NAMESPACE #endif // QT_NO_DBUS diff --git a/src/dbus/qdbusabstractadaptor_p.h b/src/dbus/qdbusabstractadaptor_p.h index 023b3b1be2..404901381b 100644 --- a/src/dbus/qdbusabstractadaptor_p.h +++ b/src/dbus/qdbusabstractadaptor_p.h @@ -92,7 +92,7 @@ public: class QDBusAdaptorConnector: public QObject { - Q_OBJECT_FAKE + Q_OBJECT public: // typedefs struct AdaptorData @@ -118,12 +118,11 @@ public: // methods void disconnectAllSignals(QObject *object); void relay(QObject *sender, int id, void **); -//public slots: - void relaySlot(void **); +public Q_SLOTS: + void relaySlot(QMethodRawArguments a); void polish(); -protected: -//signals: +Q_SIGNALS: void relaySignal(QObject *obj, const QMetaObject *metaObject, int sid, const QVariantList &args); public: // member variables diff --git a/src/tools/moc/generator.cpp b/src/tools/moc/generator.cpp index 6a74e739e6..ace3a4c9f3 100644 --- a/src/tools/moc/generator.cpp +++ b/src/tools/moc/generator.cpp @@ -1217,18 +1217,22 @@ void Generator::generateStaticMetacall() fprintf(out, "%s(", f.name.constData()); int offset = 1; - int argsCount = f.arguments.count(); - for (int j = 0; j < argsCount; ++j) { - const ArgumentDef &a = f.arguments.at(j); - if (j) - fprintf(out, ","); - fprintf(out, "(*reinterpret_cast< %s>(_a[%d]))",a.typeNameForCast.constData(), offset++); - isUsed_a = true; - } - if (f.isPrivateSignal) { - if (argsCount > 0) - fprintf(out, ", "); - fprintf(out, "%s", "QPrivateSignal()"); + if (f.isRawSlot) { + fprintf(out, "QMethodRawArguments{ _a }"); + } else { + int argsCount = f.arguments.count(); + for (int j = 0; j < argsCount; ++j) { + const ArgumentDef &a = f.arguments.at(j); + if (j) + fprintf(out, ","); + fprintf(out, "(*reinterpret_cast< %s>(_a[%d]))",a.typeNameForCast.constData(), offset++); + isUsed_a = true; + } + if (f.isPrivateSignal) { + if (argsCount > 0) + fprintf(out, ", "); + fprintf(out, "%s", "QPrivateSignal()"); + } } fprintf(out, ");"); if (f.normalizedType != "void") { diff --git a/src/tools/moc/moc.cpp b/src/tools/moc/moc.cpp index 8cc605fd8a..b98198d1d5 100644 --- a/src/tools/moc/moc.cpp +++ b/src/tools/moc/moc.cpp @@ -328,6 +328,11 @@ void Moc::parseFunctionArguments(FunctionDef *def) def->arguments.removeLast(); def->isPrivateSignal = true; } + if (def->arguments.size() == 1 + && def->arguments.constLast().normalizedType == "QMethodRawArguments") { + def->arguments.removeLast(); + def->isRawSlot = true; + } } bool Moc::testFunctionAttribute(FunctionDef *def) diff --git a/src/tools/moc/moc.h b/src/tools/moc/moc.h index 687ea2552f..6785b7f9e8 100644 --- a/src/tools/moc/moc.h +++ b/src/tools/moc/moc.h @@ -115,6 +115,7 @@ struct FunctionDef bool isConstructor = false; bool isDestructor = false; bool isAbstract = false; + bool isRawSlot = false; QJsonObject toJson() const; static void accessToJson(QJsonObject *obj, Access acs);