class Counter : public QObject { Q_OBJECT int m_value; public: int value() const { return m_value; } public slots: void setValue(int value); signals: void valueChanged(int newValue); };
void Counter::setValue(int value) { if (value != m_value) { m_value = value; emit valueChanged(value); } }
Counter a, b; QObject::connect(&a, SIGNAL(valueChanged(int)), &b, SLOT(setValue(int))); a.setValue(12); // a.value() == 12, b.value() == 12
#define signals public #define slots /* nothing */
#define Q_OBJECT \ public: \ static const QMetaObject staticMetaObject; \ virtual const QMetaObject *metaObject() const; \ virtual void *qt_metacast(const char *); \ virtual int qt_metacall(QMetaObject::Call, int, void **); \ QT_TR_FUNCTIONS /* */ \ private: \ Q_DECL_HIDDEN static void qt_static_metacall(QObject *, QMetaObject::Call, int, void **);
#define emit /* nothing */
Q_CORE_EXPORT const char *qFlagLocation(const char *method); #ifndef QT_NO_DEBUG # define QLOCATION "\0" __FILE__ ":" QTOSTRING(__LINE__) # define SLOT(a) qFlagLocation("1"#a QLOCATION) # define SIGNAL(a) qFlagLocation("2"#a QLOCATION) #else # define SLOT(a) "1"#a # define SIGNAL(a) "2"#a #endif
const QMetaObject Counter::staticMetaObject = { { &QObject::staticMetaObject, qt_meta_stringdata_Counter.data, qt_meta_data_Counter, qt_static_metacall, 0, 0 } }; const QMetaObject *Counter::metaObject() const { return QObject::d_ptr->metaObject ? QObject::d_ptr->dynamicMetaObject() : &staticMetaObject; }
struct QMetaObject { /* ... ... */ enum Call { InvokeMetaMethod, ReadProperty, WriteProperty, /*...*/ }; struct { // const QMetaObject *superdata; const QByteArrayData *stringdata; const uint *data; typedef void (*StaticMetacallFunction)(QObject *, QMetaObject::Call, int, void **); StaticMetacallFunction static_metacall; const QMetaObject **relatedMetaObjects; void *extradata; // } d; };
static const uint qt_meta_data_Counter[] = { // 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, 1, 24, 2, 0x05, // slots: name, argc, parameters, tag, flags 4, 1, 27, 2, 0x0a, // signals: parameters QMetaType::Void, QMetaType::Int, 3, // slots: parameters QMetaType::Void, QMetaType::Int, 5, 0 // eod };
struct qt_meta_stringdata_Counter_t { QByteArrayData data[6]; char stringdata[47]; }; #define QT_MOC_LITERAL(idx, ofs, len) \ Q_STATIC_BYTE_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(len, \ offsetof(qt_meta_stringdata_Counter_t, stringdata) + ofs \ - idx * sizeof(QByteArrayData) \ ) static const qt_meta_stringdata_Counter_t qt_meta_stringdata_Counter = { { QT_MOC_LITERAL(0, 0, 7), QT_MOC_LITERAL(1, 8, 12), QT_MOC_LITERAL(2, 21, 0), QT_MOC_LITERAL(3, 22, 8), QT_MOC_LITERAL(4, 31, 8), QT_MOC_LITERAL(5, 40, 5) }, ""Counter\0valueChanged\0\0newValue\0setValue\0"" ""value\0"" }; #undef QT_MOC_LITERAL
// SIGNAL 0 void Counter::valueChanged(int _t1) { void *_a[] = { 0, const_cast<void*>(reinterpret_cast<const void*>(&_t1)) }; QMetaObject::activate(this, &staticMetaObject, 0, _a); }
void Counter::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a) { if (_c == QMetaObject::InvokeMetaMethod) { Counter *_t = static_cast<Counter *>(_o); switch (_id) { case 0: _t->valueChanged((*reinterpret_cast< int(*)>(_a[1]))); break; case 1: _t->setValue((*reinterpret_cast< int(*)>(_a[1]))); break; default: ; } ... } ... }
struct QObjectPrivate::Connection { QObject *sender; QObject *receiver; union { StaticMetaCallFunction callFunction; QtPrivate::QSlotObjectBase *slotObj; }; // ConnectionList Connection *nextConnectionList; // Connection *next; Connection **prev; QAtomicPointer<const int> argumentTypes; QAtomicInt ref_; ushort method_offset; ushort method_relative; uint signal_index : 27; // ( QObjectPrivate::signalIndex()) ushort connectionType : 3; // 0 == auto, 1 == direct, 2 == queued, 4 == blocking ushort isSlotObject : 1; ushort ownArgumentTypes : 1; Connection() : nextConnectionList(0), ref_(2), ownArgumentTypes(true) { // ref_ 2 QMetaObject::Connection } ~Connection(); int method() const { return method_offset + method_relative; } void ref() { ref_.ref(); } void deref() { if (!ref_.deref()) { Q_ASSERT(!receiver); delete this; } } };
void QMetaObject::activate(QObject *sender, const QMetaObject *m, int local_signal_index, void **argv) { /* , */ activate(sender, QMetaObjectPrivate::signalOffset(m), local_signal_index, argv); } void QMetaObject::activate(QObject *sender, int signalOffset, int local_signal_index, void **argv) { int signal_index = signalOffset + local_signal_index; /* 64 , 0, , , */ if (!sender->d_func()->isSignalConnected(signal_index)) return; // /* … QML , ... */ /* , connectionLists */ QMutexLocker locker(signalSlotLock(sender)); /* connectionList ( ) */ QObjectConnectionListVector *connectionLists = sender->d_func()->connectionLists; const QObjectPrivate::ConnectionList *list = &connectionLists->at(signal_index); QObjectPrivate::Connection *c = list->first; if (!c) continue; // last, , , QObjectPrivate::Connection *last = list->last; /* , */ do { if (!c->receiver) continue; QObject * const receiver = c->receiver; const bool receiverInSameThread = QThread::currentThreadId() == receiver->d_func()->threadData->threadId; // , if ((c->connectionType == Qt::AutoConnection && !receiverInSameThread) || (c->connectionType == Qt::QueuedConnection)) { /* */ queued_activate(sender, signal_index, c, argv); continue; } else if (c->connectionType == Qt::BlockingQueuedConnection) { /* ... ... */ continue; } /* , sender() , */ QConnectionSenderSwitcher sw; if (receiverInSameThread) sw.switchSender(receiver, sender, signal_index); const QObjectPrivate::StaticMetaCallFunction callFunction = c->callFunction; const int method_relative = c->method_relative; if (c->isSlotObject) { /* … … Qt5 ... */ } else if (callFunction && c->method_offset <= receiver->metaObject()->methodOffset()) { /* callFunction ( qt_static_metacall, MOC), */ /* , metodOffset ( ) */ locker.unlock(); // callFunction(receiver, QMetaObject::InvokeMetaMethod, method_relative, argv); locker.relock(); } else { /* */ const int method = method_relative + c->method_offset; locker.unlock(); metacall(receiver, QMetaObject::InvokeMetaMethod, method, argv); locker.relock(); } // , if (connectionLists->orphaned) break; } while (c != last && (c = c->nextConnectionList) != 0); }
Source: https://habr.com/ru/post/214379/
All Articles