从回调中发出信号

时间:2014-08-13 09:36:40

标签: qt callback midi signals-slots

我正在使用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()周围是否有什么东西,但由于我自己不创建线程(信号是从回调发送的),我不知道是否需要使用它。< / p>

2 个答案:

答案 0 :(得分:1)

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

虽然您应该从QByteArray创建data以传递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

}

答案 1 :(得分:0)

在上次connect()来电中,您传递了thisMidiTest::onQuarterFrame作为接收器对象和方法。我敢打赌this不是MidiTest的实例,是吗?

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

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