3

我正在使用一个 API,它要求我将函数指针作为回调传递。我正在尝试从我的 C++ 类中使用此 API,但出现编译错误。

API 定义为:

typedef void (__stdcall *STREAM_CALLBACK)(void *userdata);

__declspec(dllimport) int __stdcall set_stream_callback(
    STREAM_CALLBACK streamCB, void *userdata);

第三方提供的一个示例文件是:

void __stdcall streamCB(void *userdata)
{
  // callback implementation
}

int main(int argc, const char argv[])
{
  int mid = 0;
  set_stream_callback(streamCB, &mid);
}

这很好用。但是,当我尝试在课堂上使用它时,出现错误:

错误 C3867:“MyClass::streamCB”:函数调用缺少参数列表;使用 '&MyClass::streamCB' 创建指向成员的指针

使用建议

&MyClass::streamCB

不起作用。我知道 set_stream_callback 只接受非成员函数。

问题非常类似于 如何将类成员函数作为回调传递? 约翰内斯在其中提出了一个简洁的建议,但是我不太理解。如果我正确地认为它与这个问题有关,任何人都可以扩展一下吗?

我试过了:

void __stdcall MyClass::streamCB(void *userdata)
{
  // callback implementation
}

static void MyClass::Callback( void * other_arg, void * this_pointer ) {
    MyClass * self = static_cast<ri::IsiDevice*>(this_pointer);
    self->streamCB( other_arg );
}

//and in the constructor
int mid = 0;
set_stream_callback(&MyClass::Callback, &mid);

错误 C2664:“set_stream_callback”:无法将参数 1 从“void (__cdecl *)(void *,void *)”转换为“STREAM_CALLBACK”

我该如何解决这个问题?


Edit1:另外,我想userdatastreamCB回调中使用。

4

2 回答 2

4

从仅采用非成员函数的回调中调用成员函数的想法是为您的成员函数创建一个包装器。包装器从某个地方获取一个对象,然后调用成员函数。如果回调设计得相当好,它将允许您传递一些用于识别对象的“用户数据”。不幸的是,您遗漏了有关您的课程的任何详细信息,因此我假设它看起来像这样:

class MyClass {
public:
    void streamCB() {
         // whatever
    }
    // other members, constructors, private data, etc.
};

有了这个,你可以像这样设置你的回调:

void streamCBWrapper(void* userData) {
    static_cast<MyClass*>(userData)->streamCB()
}

int main() {
    MyClass object;
   set_stream_callback(&streamCBWrapper, &object);
   // ...
}

你可以玩各种游戏来创建streamCBWrapper函数(例如,你可以让它成为static你的类的成员),但归根结底都是一样的:你需要从用户数据中恢复你的对象并调用成员函数这个对象。

于 2012-10-29T21:09:28.947 回答
2

您可以通过将 userdata 转换为 MyClass 的属性来实现您想要做的事情。然后你不必将它传递给 MyClass::Callback,这是不可能的,因为你只能传递一个参数,它就是对象实例。这是一个例子。

void __stdcall MyClass::streamCB()
{
  // callback implementation
}

static void MyClass::Callback(void * this_pointer ) {
    MyClass * self = static_cast<MyClass>(this_pointer);
    self->streamCB();
}

MyClass::MyClass(void *userdata) {
    // do whatever you need to do with userdata
    // (...)
    // and setup the callback at C level
    set_stream_callback(&MyClass::Callback, (void *)this);
}

在您的示例中,该int mid变量将成为该类的属性,因此可以从回调 implementation 访问streamCB

于 2012-10-29T21:04:38.210 回答