QObject::connect
. The value of such an implementation will tend to zero.QObject
class. What for? All classes with meta-information must be QObject
descendants and have the Q_OBJECT
macro in order for moc to generate meta-information. class Q_CORE_EXPORT QObjectData { public: virtual ~QObjectData() = 0; QObject *q_ptr; QObject *parent; QObjectList children; uint isWidget : 1; uint blockSig : 1; uint wasDeleted : 1; uint isDeletingChildren : 1; uint sendChildEvents : 1; uint receiveChildEvents : 1; uint isWindow : 1; //for QWindow uint unused : 25; int postedEvents; QDynamicMetaObjectData *metaObject; QMetaObject *dynamicMetaObject() const; }; class Q_CORE_EXPORT QObject { Q_OBJECT Q_PROPERTY(QString objectName READ objectName WRITE setObjectName NOTIFY objectNameChanged) Q_DECLARE_PRIVATE(QObject) /// protected: QScopedPointer<QObjectData> d_ptr; static const QMetaObject staticQtMetaObject; /// }
#include <QObject> class A : public QObject { Q_OBJECT public: explicit A(QObject *parent = 0); ~A(); signals: void signal(); public slots: void slot(){} };
/// QT_BEGIN_MOC_NAMESPACE struct qt_meta_stringdata_A_t { QByteArrayData data[4]; char stringdata[15]; }; #define QT_MOC_LITERAL(idx, ofs, len) \ Q_STATIC_BYTE_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(len, \ qptrdiff(offsetof(qt_meta_stringdata_A_t, stringdata) + ofs \ - idx * sizeof(QByteArrayData)) \ ) static const qt_meta_stringdata_A_t qt_meta_stringdata_A = { { QT_MOC_LITERAL(0, 0, 1), // "A" QT_MOC_LITERAL(1, 2, 6), // "signal" QT_MOC_LITERAL(2, 9, 0), // "" QT_MOC_LITERAL(3, 10, 4) // "slot" }, "A\0signal\0\0slot" }; #undef QT_MOC_LITERAL static const uint qt_meta_data_A[] = { // content: 7, // revision 0, // classname 0, 0, // classinfo 2, 14, // methods 0, 0, // properties 0, 0, // enums/sets 0, 0, // constructors 0, // flags 1, // signalCount // signals: name, argc, parameters, tag, flags 1, 0, 24, 2, 0x06 /* Public */, // slots: name, argc, parameters, tag, flags 3, 0, 25, 2, 0x0a /* Public */, // signals: parameters QMetaType::Void, // slots: parameters QMetaType::Void, 0 // eod }; void A::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a) { if (_c == QMetaObject::InvokeMetaMethod) { A *_t = static_cast<A *>(_o); switch (_id) { case 0: _t->signal(); break; case 1: _t->slot(); break; default: ; } } else if (_c == QMetaObject::IndexOfMethod) { /// } Q_UNUSED(_a); } /// ! ! const QMetaObject A::staticMetaObject = { { &QObject::staticMetaObject, qt_meta_stringdata_A.data, qt_meta_data_A, qt_static_metacall, Q_NULLPTR, Q_NULLPTR} }; const QMetaObject *A::metaObject() const { return QObject::d_ptr->metaObject ? QObject::d_ptr->dynamicMetaObject() : &staticMetaObject; } int A::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 < 2) qt_static_metacall(this, _c, _id, _a); _id -= 2; } else if (_c == QMetaObject::RegisterMethodArgumentMetaType) { if (_id < 2) *reinterpret_cast<int*>(_a[0]) = -1; _id -= 2; } return _id; } // SIGNAL 0 void A::signal() { QMetaObject::activate(this, &staticMetaObject, 0, Q_NULLPTR); } QT_END_MOC_NAMESPACE
QDynamicMetaObjectData * QObjectData::metaObject
and the function QMetaObject * QObjectData::dynamicMetaObject() const
. Therefore, it remains to learn how to work with them and how Qt works with them. /// struct QAbstractDynamicMetaObject; struct Q_CORE_EXPORT QDynamicMetaObjectData { virtual ~QDynamicMetaObjectData() {} virtual void objectDestroyed(QObject *) { delete this; } virtual QAbstractDynamicMetaObject *toDynamicMetaObject(QObject *) = 0; /// metaObject virtual int metaCall(QObject *, QMetaObject::Call, int _id, void **) = 0;/// //. }; /// , . struct Q_CORE_EXPORT QAbstractDynamicMetaObject : public QDynamicMetaObjectData, public QMetaObject { virtual QAbstractDynamicMetaObject *toDynamicMetaObject(QObject *) { return this; } virtual int createProperty(const char *, const char *) { return -1; }/// . virtual int metaCall(QObject *, QMetaObject::Call c, int _id, void **a) { return metaCall(c, _id, a); } virtual int metaCall(QMetaObject::Call, int _id, void **) { return _id; } // Compat overload }; ///
QObject::d_ptr->metaObject
in any QObject
heir, then no calls to signals and slots will pass by us (by the way, an excellent tool for debugging signals and slots can be done), and you can take a place for your signals and slots. In general, to do everything that will support our sick imagination, but I was more inspired by the creation of a meta-object, which could add signals and slots, so I will highlight here exactly the preparation for the creation of such a meta-object. struct Q_CORE_EXPORT QMetaObject { /// struct { // private data const QMetaObject *superdata;/// const QByteArrayData *stringdata;/// ( , , ) const uint *data;/// ( , , ) typedef void (*StaticMetacallFunction)(QObject *, QMetaObject::Call, int, void **); StaticMetacallFunction static_metacall;/// , . const QMetaObject * const *relatedMetaObjects;///, void *extradata; //reserved for future use } d; }
stringdata
and data
, or completely rewrite all the functions of the QMetaObject
class. Out of 2 evils, I chose the least - I decided to fill in this data, because the search for this data will be done using Qt tools and it will be no slower to search for ordinary metaobjects (yes, this is premature optimization). struct qt_meta_stringdata_A_t { QByteArrayData data[4]; char stringdata[15]; }; #define QT_MOC_LITERAL(idx, ofs, len) \ Q_STATIC_BYTE_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(len, \ qptrdiff(offsetof(qt_meta_stringdata_A_t, stringdata) + ofs \ - idx * sizeof(QByteArrayData)) \ ) static const qt_meta_stringdata_A_t qt_meta_stringdata_A = { { QT_MOC_LITERAL(0, 0, 1), // "A" QT_MOC_LITERAL(1, 2, 6), // "signal" QT_MOC_LITERAL(2, 9, 0), // "" QT_MOC_LITERAL(3, 10, 4) // "slot" }, "A\0signal\0\0slot" }; #undef QT_MOC_LITERAL
QByteArrayData
, which contains relative references to strings (relative to QByteArrayData
itself). Thus, we can safely place each line in memory separately, and not together, as the MOC did. static const uint qt_meta_data_A[] = { ///1 // content: 7, // revision 0, // classname 0, 0, // classinfo 2, 14, // methods 0, 0, // properties 0, 0, // enums/sets 0, 0, // constructors 0, // flags 1, // signalCount ///2 // signals: name, argc, parameters, tag, flags 1, 0, 24, 2, 0x06 /* Public */, // slots: name, argc, parameters, tag, flags 3, 0, 25, 2, 0x0a /* Public */, ///3 // signals: parameters QMetaType::Void, // slots: parameters QMetaType::Void, 0 // eod };
QMetaObjectPrivate
class: struct QMetaObjectPrivate { enum { OutputRevision = 7 }; // Used by moc, qmetaobjectbuilder and qdbus int revision; int className; int classInfoCount, classInfoData; int methodCount, methodData; int propertyCount, propertyData; int enumeratorCount, enumeratorData; int constructorCount, constructorData; //since revision 2 int flags; //since revision 3 int signalCount; //since revision 4 // revision 5 introduces changes in normalized signatures, no new members // revision 6 added qt_static_metacall as a member of each Q_OBJECT and inside QMetaObject itself // revision 7 is Qt 5 /// , }
DataMethodInfo
): struct DataMethodInfo{ uint name;/// ( ) uint argsCount; /// uint argOffset; /// offset uint tag;/// , uint flags;/// private/protected/public - , };
QMetaType::Void
. Next comes the listing of all types of arguments. Namely, if we have the QString testString (QString src, QString dst)
method QString testString (QString src, QString dst)
, then there will be 2 QMetaType :: QString. If the method has no arguments, then we do not fill in anything. And after listing the types of arguments, there is a list of the names of these arguments. Thus, for our QString testString( QString src, QString dst )
method QString testString( QString src, QString dst )
the metadata code would be: static const qt_meta_stringdata_A_t qt_meta_stringdata_A = { { QT_MOC_LITERAL(0, 0, 1), // "A" QT_MOC_LITERAL(1, 2, 6), // "signal" QT_MOC_LITERAL(2, 9, 0), // "" QT_MOC_LITERAL(3, 10, 4) // "slot" QT_MOC_LITERAL(4, 15, 10) // "testString" QT_MOC_LITERAL(5, 26, 3) // "src" QT_MOC_LITERAL(6, 30, 3) // "dst" }, "A\0signal\0\0slot\0testString\0src\dst" }; static const uint qt_meta_data_A[] = { ///1 // 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 ///2 // signals: name, argc, parameters, tag, flags 1, 0, 29, 2, 0x06 /* Public */, // slots: name, argc, parameters, tag, flags 3, 0, 30, 2, 0x0a /* Public */, 4, 2, 31, 2, 0x0a /* Public */, ///3 // signals: parameters QMetaType::Void, // slots: parameters QMetaType::Void, ////----------------------------------------------------------------- ///| return | Arguments Type | names | QMetaType::QString , QMetaType::QString, QMetaType::QString, 5 , 6 0 // eod };
Source: https://habr.com/ru/post/258441/
All Articles