从回调中发出信号

Posted

技术标签:

【中文标题】从回调中发出信号【英文标题】:Emitting signal from callback 【发布时间】:2014-08-13 09:36:40 【问题描述】:

我正在使用RtMidi 库在我的Qt 应用程序中处理midi 消息,但我遇到了槽触发器问题:

我的 PhMidiInput 对象正在根据特定的 midi 消息从 RtMidi 回调发出信号,但插槽并不总是被触发。

这是 PhMidiInput 类的一部分:

class PhMidiInput : QObject

    Q_OBJECT
public:
    void PhMidiInput() 
signals:
    void quarterFrame(unsigned char data);
private:
    static void callback(double, std::vector< unsigned char > *message, void *userData ) 
        PhMidiInput *midiInput = (PhMidiInput*)userData;
        if(midiInput)
            midiInput->onMessage(message);
    

    void onMessage(std::vector<unsigned char> *message) 
        ...
        emit quarterFrame(data);
        ...
    


连接到 lambda 仿函数有效:

PhMidiInput midiIn;
int quarterFrameCount;

connect(&midiIn, &PhMidiInput::quarterFrame, [&](unsigned char data) 
    quarterFrameCount++;
);

连接到我的应用程序窗口可以:

// MyWindow inherits from QMainWindow
connect(_midiIn, &PhMidiInput::quarterFrame, this, &MyWindow::onQuarterFrame);

当尝试连接到继承自 QObject 的自定义类 (MidiTest) 时,它不会触发:

connect(_midiIn, &PhMidiInput::quarterFrame, this, &MidiTest::onQuarterFrame);

我想知道QObject::moveToThread() 周围是否有什么东西,但由于我自己没有创建线程(信号是从回调发送的)我不知道我是否需要使用它。

【问题讨论】:

【参考方案1】:

就像从回调中调用emit obj-&gt;quarterFrame(data); 一样简单。如果连接类型是默认的,那么这将是完全线程安全的。

尽管您应该从data 创建一个QByteArray 以传递,因为data 在调用插槽时可能无效。

void callback(..., void* user)
    //user is the standard void* in most callbacks passed as reinterpret_cast<void*>(this)
    unsigned char* data = ...;
    QByteArray bytes(data);
    emit reinterpret_cast<PhMidiInput>(user)->quarterFrame(bytes);//calling the signal which will behave as you'd expect


【讨论】:

其实data就是一个简单的unsigned char。信号是从回调调用的方法发出的。我将添加缺少的代码。 @MartinDelille 抱歉,我以为我在那里看到了*【参考方案2】:

在最后一次connect() 调用中,您将thisMidiTest::onQuarterFrame 作为接收器对象和方法传递。我敢打赌this 不是MidiTest 的实例,是吗?

这里的问题是您从MidiTest 传递SLOT 方法,而接收器对象是this,它不是MidiTest 的实例。将接收者从 this 更改为 MidiTest 的某个实例。

我很惊讶这段代码在运行时不会让您的应用程序崩溃。

【讨论】:

是的 this 在第三种情况下是 MidiTest 类实例(在第二种情况下是 MyWindow 类实例.

以上是关于从回调中发出信号的主要内容,如果未能解决你的问题,请参考以下文章

Python QT发出信号没有调用回调函数

无法向服务 com.apple.WebKit.WebContent 发出信号

PyQt跨线程发出信号

3信号与槽

信号和槽机制

从其他线程发出信号