c++ - 打印信号/槽的跟踪称为

标签 c++ qt signals-slots

有没有办法打印被调用的信号和槽?

我在 Qt 中遇到了奇怪的死锁,这种死锁仅在多个线程的特定条件下发生,我想知道调用信号/槽的顺序。

当然,对于槽,我编写方法体,在最坏的情况下,我可以手动添加方法的打印。但是信号的主体是自动生成的,所以这是不可能的,除非我编写一个自定义的 moc,这对于这个任务来说似乎有点过分了......

最佳答案

如果利用内置 Hook ,则可以自动检测所有信号以及使用 Qt 4 connect 语法连接的所有插槽。不幸的是,QtPrivate::QSlotObject 没有实现这些钩子(Hook):使用 Qt 5 语法连接的插槽需要手动检测(例如,通过将仿函数连接到它们,或向它们添加代码)。

连接信号可以依赖信号通知。没有信号的对象以及具有其他连接的对象的某些信号将不会被报告。这可能就是您想要的。

因此:

// https://github.com/KubaO/stackoverflown/tree/master/questions/signal-spy-39597233
#include <QtCore>
#include <private/qobject_p.h>

int signalToMethodIndex(const QMetaObject * mo, int signal)
{
    Q_ASSERT(signal >= 0);
    for (int i = 0; i < mo->methodCount(); ++i) {
        if (mo->method(i).methodType() == QMetaMethod::Signal) {
            if (signal == 0) return i;
            -- signal;
        }
    }
    return -1;
}

class Spy {
    static QThreadStorage<bool> entered;
    static void signalBegin(QObject *caller, int signalIndex, void **) {
        if (entered.localData()) return;
        QScopedValueRollback<bool> roll{entered.localData(), true};
        auto index = signalToMethodIndex(caller->metaObject(), signalIndex);
        if (index >= 0)
            qDebug() << "SIGNAL" << caller << caller->metaObject()->method(index).methodSignature();
    }
    static void slotBegin(QObject *caller, int index, void **) {
        if (entered.localData()) return;
        QScopedValueRollback<bool> roll{entered.localData(), true};
        qDebug() << "SLOT" << caller << caller->metaObject()->method(index).methodSignature();
    }
public:
   static void start() {
       QSignalSpyCallbackSet set{&signalBegin, &slotBegin, nullptr, nullptr};
       qt_signal_spy_callback_set = set;
   }
};
QThreadStorage<bool> Spy::entered;


struct Class : QObject {
    Q_SIGNAL void aSignal();
    Q_SLOT void aSlot() { qDebug() << "slot"; }
    Q_OBJECT
};

int main(int argc, char ** argv) {
    Spy::start();
    QCoreApplication app{argc, argv};
    Class obj;
    QObject::connect(&obj, SIGNAL(aSignal()), &obj, SLOT(aSlot()));
    obj.setObjectName("obj");
    emit obj.aSignal();
}
#include "main.moc"

输出:

SIGNAL Class(0x7fff51901af0, name = "obj") "objectNameChanged(QString)"
SIGNAL Class(0x7fff51901af0, name = "obj") "aSignal()"
SLOT Class(0x7fff51901af0, name = "obj") "aSlot()"
slot

关于c++ - 打印信号/槽的跟踪称为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39597233/

相关文章:

c++ - Qt Windows 获取鼠标光标图标

c++ - C++ 类型特征意义上的标量的目的是什么?

c++ - 将数组连接到 Qt 中的信号槽机制

c++ - 如何通过单击它们在运行时编辑 QListWidget 中的文本?

python - 使用 QThread 时启动 QTimer 时出现问题

c++ if语句带有额外条件

c++ - 在程序员创建时自动将类型派生类(不是实例)添加到列表中。 C++

c++ - QVector 总是推回 0?

c++ - 使用 pushButton c++ QT 连接表单

android - "module “QtQuick” 未安装”(安卓移植)