非成员功能指针作为API中的回调对成员函数

non-member function pointer as a callback in API to member function

本文关键字:成员 回调 函数 功能 指针 API      更新时间:2023-10-16

我正在使用一个API,该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 *)'to'stream_callback'

我该如何解决?


edit1:另外,我想在streamCB回调内使用userdata

从呼叫函数调用成员函数的想法仅对您的成员函数创建包装器。包装器从某个地方获得对象,然后调用成员函数。如果回调的设计合理,它将允许您传递某些用于识别对象的"用户数据"。不幸的是,您遗漏了有关您班级的任何细节,所以我假设它看起来像这样:

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成员),但所有这些都归结为相同:您需要从用户数据和用户数据中还原对象在此对象上调用成员功能。

您可以通过将UserData变成MyClass的属性来实现您想做的事情。然后,您不必将其传递给myClass ::回调,这是不可能的,因为您只能传递一个参数,并且它将是对象实例。这是一个例子。

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变量将成为该类的属性,因此可以从回调实现streamCB

访问