c++ - 使用面向对象的 C 库

标签 c++ c templates gcc function-pointers

我正在使用一个用 C 编写的库,它允许我读取和写入 midi 文件。尽管我找到了另一个用 C++ 编写的适用于我的库,但我仍在为这个事实而苦苦挣扎:我怎么能将 C 库与对象/类一起使用。该库有一个调用,该调用采用 midi 文件的路径,然后是一些为特定 midi 事件类型调用的函数指针。所以它看起来像这样(摘要):

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, ...);

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

关于c++ - 使用面向对象的 C 库,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22359434/

相关文章:

c++ - 从 R 中的一组观察结果创建频率 vector 的矢量化方法?

c++ - 将 const char* 类型转换为 int 数组

c - 从 sys/socket.h 了解 msghdr 结构

c++ - 为什么不能用兼容类型的 std::tuple 按元素构造 std::tuple?

c++ rest sdk http_listener 作为网络服务器

c++ - (OpenCV4.1)/usr/bin/ld : cannot find -lopencv_nonfree

c - 为什么我们将字符串存储在字符指针中,例如 fopen(); 中?

c - 在C中查找二维数组中最长的字符串

C++ 类型删除/类型封装?发现型

c++ - 尝试创建线程的问题