Skip to content

Commit

Permalink
Add support for slots to receive the raw void ** arguments array
Browse files Browse the repository at this point in the history
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 <[email protected]>
  • Loading branch information
laknoll committed Oct 7, 2019
1 parent 1acc444 commit 4c57103
Show file tree
Hide file tree
Showing 9 changed files with 52 additions and 227 deletions.
15 changes: 15 additions & 0 deletions src/corelib/kernel/qmetaobject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 4 additions & 0 deletions src/corelib/kernel/qobjectdefs.h
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,10 @@ class QMetaEnum;
class QMetaProperty;
class QMetaClassInfo;

struct QMethodRawArguments
{
void **arguments;
};

class Q_CORE_EXPORT QGenericArgument
{
Expand Down
7 changes: 3 additions & 4 deletions src/corelib/statemachine/qsignaleventgenerator_p.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
92 changes: 2 additions & 90 deletions src/corelib/statemachine/qstatemachine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<QSignalEventGenerator *>(_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<void*>(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<QStateMachine*>(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)
Expand Down
118 changes: 2 additions & 116 deletions src/dbus/qdbusabstractadaptor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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\").",
Expand Down Expand Up @@ -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<QDBusAdaptorConnector *>(_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<void*>(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<void*>(reinterpret_cast<const void*>(&_t1)), const_cast<void*>(reinterpret_cast<const void*>(&_t2)), const_cast<void*>(reinterpret_cast<const void*>(&_t3)), const_cast<void*>(reinterpret_cast<const void*>(&_t4)) };
QMetaObject::activate(this, &staticMetaObject, 0, _a);
}

QT_END_NAMESPACE

#endif // QT_NO_DBUS
9 changes: 4 additions & 5 deletions src/dbus/qdbusabstractadaptor_p.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ class QDBusAbstractAdaptorPrivate: public QObjectPrivate

class QDBusAdaptorConnector: public QObject
{
Q_OBJECT_FAKE
Q_OBJECT

public: // typedefs
struct AdaptorData
Expand All @@ -118,12 +118,11 @@ class QDBusAdaptorConnector: public QObject
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
Expand Down
28 changes: 16 additions & 12 deletions src/tools/moc/generator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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") {
Expand Down
5 changes: 5 additions & 0 deletions src/tools/moc/moc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
1 change: 1 addition & 0 deletions src/tools/moc/moc.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down

0 comments on commit 4c57103

Please sign in to comment.