如何明智地分配静态 RtMidi 回调对象?

Posted

技术标签:

【中文标题】如何明智地分配静态 RtMidi 回调对象?【英文标题】:How can i assign static RtMidi callbacks object wise? 【发布时间】:2013-05-12 14:51:12 【问题描述】:

我正在使用 C++ RtMidi 库从两个相同的设备(Novation 启动板)读取 MIDI 输入。 两个启动板都“存在”在自己的对象中,打开自己的 MIDI 端口,并且(应该)设置自己的回调方法。但是,如果我按下启动板上的按钮,两个设备都会将 MIDI 数据扔到同一个回调函数中(最后分配的那个)。 我希望回调函数是特定于对象的,而不是特定于类的。经过大量研究和修补后,我怀疑问题与回调函数被声明为静态(如 RtMidi 文档所建议)并因此声明为类范围而不是对象范围的事实有关。

如何修复代码,以便将启动板生成的 MIDI 事件发送到其“自己的”回调函数?

这是(精简的)代码:

launchpad.cpp

class launchpad 
public:
    launchpad(int paramPortId, std::string paramPosition);
private:
    static void listenerCallback(double deltatime, std::vector< unsigned char > *message, void *userData);
    static std::string position;
;

std::string launchpad::position;

void launchpad::listenerCallback(double deltatime, std::vector< unsigned char > *message, void *userData) 
    unsigned int nBytes = message->size();
    for (unsigned int i = 0; i < nBytes; i++)
        std::cout << position << "Byte " << i << " = " << (int) message->at(i) << ", ";
    if (nBytes > 0)
        std::cout << "stamp = " << deltatime << std::endl;


launchpad::launchpad(int paramPortId, std::string paramPosition) 

    RtMidiIn *input = new RtMidiIn();
    launchpad::position = paramPosition;
    std::cout << "Launchpad found at port # " << paramPortId << " assigned position: " << position << std::endl;

    input->setCallback(&listenerCallback);
    input->openPort(paramPortId);

main.cpp

int main(int argc, char *argv[]) 

   RtMidiIn *infoDevice;
   launchpad *leftLaunchpad = 0;
   launchpad *rightLaunchpad = 0;
   int launchpadIndex = 0;
   infoDevice = new RtMidiIn();
   unsigned int nPorts = infoDevice->getPortCount();
   string portName;

   for (unsigned int i = 0; i < nPorts; i++) 
       portName = infoDevice->getPortName(i);
       if (portName == "Launchpad") 
           if (launchpadIndex == 0) 
               leftLaunchpad = new launchpad(i, "left");
               launchpadIndex++;
            else if (launchpadIndex == 1) 
               rightLaunchpad = new launchpad(i, "right");
               launchpadIndex++;
           
       


    char input;
    std::cin.get(input);
    return 0;

非常感谢任何帮助。谢谢

【问题讨论】:

【参考方案1】:

listenerCallback 可以是任何非类的静态 C 函数

然后使用 输入->setCallback(&listenerCallback,(void *)this); 并且 userdata 会告诉你叫什么

【讨论】:

正确,但是一个术语上的抱怨;)“不是来自类”是非常不准确的,因为static 成员方法绝对是class 的一部分。这就是为什么,正如您所指出的,它可以访问包括private 在内的实例成员,只要给它一个this 指针/引用即可使用。它是类的一部分,尽管不绑定到特定的实例。非类函数只能访问公共成员/方法——在现实中可能没有多大用处。 设置用户回调提供指向 userData 的指针(可以是指向任何适当的用户数据结构的指针)即使在原始 RtMidi 文档中也非常谨慎和模棱两可地记录。谢谢

以上是关于如何明智地分配静态 RtMidi 回调对象?的主要内容,如果未能解决你的问题,请参考以下文章

如何将回调和中断服务函数进行结合?

C++ 访问静态分配对象的成员

静态方法内存分配

从回调中发出信号

java关键字---static

如何在类别中创建 UITableViewCell 明智地排列 JSON 对象