从回调中发出信号
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->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()
调用中,您将this
和MidiTest::onQuarterFrame
作为接收器对象和方法传递。我敢打赌this
不是MidiTest
的实例,是吗?
这里的问题是您从MidiTest
传递SLOT 方法,而接收器对象是this
,它不是MidiTest
的实例。将接收者从 this
更改为 MidiTest
的某个实例。
我很惊讶这段代码在运行时不会让您的应用程序崩溃。
【讨论】:
是的 this 在第三种情况下是 MidiTest 类实例(在第二种情况下是 MyWindow 类实例.以上是关于从回调中发出信号的主要内容,如果未能解决你的问题,请参考以下文章