6. Qt 信号与信号槽 (6)- QObject::connect

it2026-09-24  16

函数调用流程为: QObject::connect ->QObject::connectImpl -> QObjectPrivate::connectImpl -> QObjectPrivate::get(s)->addConnection

class QObject{ static inline QMetaObject::Connection connect(const typename QtPrivate::FunctionPointer<Func1>::Object *sender, Func1 signal, const typename QtPrivate::FunctionPointer<Func2>::Object *receiver, Func2 slot, Qt::ConnectionType type = Qt::AutoConnection) { ... return connectImpl(sender, reinterpret_cast<void **>(&signal), receiver, reinterpret_cast<void **>(&slot), new QtPrivate::QSlotObject<Func2, typename QtPrivate::List_Left<typename SignalType::Arguments, SlotType::ArgumentCount>::Value, typename SignalType::ReturnType>(slot), type, types, &SignalType::Object::staticMetaObject); ... } QMetaObject::Connection QObject::connectImpl(const QObject *sender, void **signal, const QObject *receiver, void **slot, QtPrivate::QSlotObjectBase *slotObj, Qt::ConnectionType type, const int *types, const QMetaObject *senderMetaObject) { if (!signal) { qWarning("QObject::connect: invalid null parameter"); if (slotObj) slotObj->destroyIfLastRef(); return QMetaObject::Connection(); } int signal_index = -1; void *args[] = { &signal_index, signal }; for (; senderMetaObject && signal_index < 0; senderMetaObject = senderMetaObject->superClass()) { senderMetaObject->static_metacall(QMetaObject::IndexOfMethod, 0, args); if (signal_index >= 0 && signal_index < QMetaObjectPrivate::get(senderMetaObject)->signalCount) break; } if (!senderMetaObject) { qWarning("QObject::connect: signal not found in %s", sender->metaObject()->className()); slotObj->destroyIfLastRef(); return QMetaObject::Connection(0); } signal_index += QMetaObjectPrivate::signalOffset(senderMetaObject); return QObjectPrivate::connectImpl(sender, signal_index, receiver, slot, slotObj, type, types, senderMetaObject); } QMetaObject::Connection QObjectPrivate::connectImpl(const QObject *sender, int signal_index, const QObject *receiver, void **slot, QtPrivate::QSlotObjectBase *slotObj, Qt::ConnectionType type, const int *types, const QMetaObject *senderMetaObject) { if (!sender || !receiver || !slotObj || !senderMetaObject) { const char *senderString = sender ? sender->metaObject()->className() : senderMetaObject ? senderMetaObject->className() : "Unknown"; const char *receiverString = receiver ? receiver->metaObject()->className() : "Unknown"; qWarning("QObject::connect(%s, %s): invalid null parameter", senderString, receiverString); if (slotObj) slotObj->destroyIfLastRef(); return QMetaObject::Connection(); } QObject *s = const_cast<QObject *>(sender); QObject *r = const_cast<QObject *>(receiver); QOrderedMutexLocker locker(signalSlotLock(sender), signalSlotLock(receiver)); if (type & Qt::UniqueConnection && slot) { QObjectConnectionListVector *connectionLists = QObjectPrivate::get(s)->connectionLists; if (connectionLists && connectionLists->count() > signal_index) { const QObjectPrivate::Connection *c2 = (*connectionLists)[signal_index].first; while (c2) { if (c2->receiver == receiver && c2->isSlotObject && c2->slotObj->compare(slot)) { slotObj->destroyIfLastRef(); return QMetaObject::Connection(); } c2 = c2->nextConnectionList; } } type = static_cast<Qt::ConnectionType>(type ^ Qt::UniqueConnection); } QScopedPointer<QObjectPrivate::Connection> c(new QObjectPrivate::Connection); c->sender = s; c->signal_index = signal_index; c->receiver = r; c->slotObj = slotObj; c->connectionType = type; c->isSlotObject = true; if (types) { c->argumentTypes.store(types); c->ownArgumentTypes = false; } QObjectPrivate::get(s)->addConnection(signal_index, c.data()); QMetaObject::Connection ret(c.take()); locker.unlock(); QMetaMethod method = QMetaObjectPrivate::signal(senderMetaObject, signal_index); Q_ASSERT(method.isValid()); s->connectNotify(method); return ret; } QMetaObject::Connection QMetaObject::connect(const QObject *sender, int signal_index, const QObject *receiver, int method_index, int type, int *types) { const QMetaObject *smeta = sender->metaObject(); signal_index = methodIndexToSignalIndex(&smeta, signal_index); return Connection(QMetaObjectPrivate::connect(sender, signal_index, smeta, receiver, method_index, 0, //FIXME, we could speed this connection up by computing the relative index type, types)); } /*! \internal Same as the QMetaObject::connect, but \a signal_index must be the result of QObjectPrivate::signalIndex method_index is relative to the rmeta metaobject, if rmeta is null, then it is absolute index the QObjectPrivate::Connection* has a refcount of 2, so it must be passed to a QMetaObject::Connection */ QObjectPrivate::Connection *QMetaObjectPrivate::connect(const QObject *sender, int signal_index, const QMetaObject *smeta, const QObject *receiver, int method_index, const QMetaObject *rmeta, int type, int *types) { QObject *s = const_cast<QObject *>(sender); QObject *r = const_cast<QObject *>(receiver); int method_offset = rmeta ? rmeta->methodOffset() : 0; Q_ASSERT(!rmeta || QMetaObjectPrivate::get(rmeta)->revision >= 6); QObjectPrivate::StaticMetaCallFunction callFunction = rmeta ? rmeta->d.static_metacall : 0; QOrderedMutexLocker locker(signalSlotLock(sender), signalSlotLock(receiver)); if (type & Qt::UniqueConnection) { QObjectConnectionListVector *connectionLists = QObjectPrivate::get(s)->connectionLists; if (connectionLists && connectionLists->count() > signal_index) { const QObjectPrivate::Connection *c2 = (*connectionLists)[signal_index].first; int method_index_absolute = method_index + method_offset; while (c2) { if (!c2->isSlotObject && c2->receiver == receiver && c2->method() == method_index_absolute) return 0; c2 = c2->nextConnectionList; } } type &= Qt::UniqueConnection - 1; } QScopedPointer<QObjectPrivate::Connection> c(new QObjectPrivate::Connection); c->sender = s; c->signal_index = signal_index; c->receiver = r; c->method_relative = method_index; c->method_offset = method_offset; c->connectionType = type; c->isSlotObject = false; c->argumentTypes.store(types); c->nextConnectionList = 0; c->callFunction = callFunction; QObjectPrivate::get(s)->addConnection(signal_index, c.data()); locker.unlock(); QMetaMethod smethod = QMetaObjectPrivate::signal(smeta, signal_index); if (smethod.isValid()) s->connectNotify(smethod); return c.take(); }
最新回复(0)