使用面向对象的c库

use a c lib object orientated

本文关键字:面向对象的      更新时间:2023-10-16

我正在使用一个用C编写的库,它允许我读取和写入midi文件。虽然我发现了另一个用c++编写的库,但我仍然在努力解决这个问题:我怎么能把C库和对象/类一起使用呢?这个库有一个调用,它接受midi文件的路径,然后是针对特定midi事件类型调用的一些函数指针。所以它看起来像这样(abstract):

int main( int argc, char** args )
{
    readMidi( args[ 1 ], onMidiEvent, onSysEvent, onError, ... );
}

我尝试使用一个指针指向一个类的实例来收集演奏的音符:

class MidiNoteList;
template < MidiNoteList* VMidi > onError( short errmsg, char* msg ) { ... }
...
int main( int argc, char** args )
{
    MidiNoteList* m( new MidiNoteList( ) );
    readMidi( args[ 1 ], onMidiEvent< m >, onSysEvent< m >, onError< m >, ... );
}

GCC规定m不能用作常量表达式。我知道m在编译时必须是常数,所以我知道为什么我不能这样做。但我如何用另一种方式解决这个"问题"呢?

通常这样的库使用一个额外的void *参数,该参数传递给接受函数指针的函数,并传递给所有回调函数。如果你有,你可以用它来传递你的对象指针,将它强制转换为void,然后返回:

class MyObject;
void errCallback(void *m, short errcode, char *errmsg) {
    static_cast<MyObject *>(m)->error(errcode, errmsg);
}
    :
    MyObject *m = new MyObject();
    callLibrary(..., errCallback, m, ...);

如果库没有给你额外的参数,你就有问题了——在回调函数中获取额外数据的唯一方法是使用全局变量:

static MyObject *m;
void errCallback(short errcode, char *errmsg) {
    m->error(errcode, errmsg);
}
    :
    m = new MyObject();
    callLibrary(..., errCallback, ...);

这里的问题是,您需要为每个希望接收回调的不同对象声明一个新的回调函数(和全局变量)。如果您动态地创建了许多这样的对象,那么管理起来会变得很困难。