如何使用C++成员函数作为C框架的回调函数

Oak*_*tes 14 c c++ callback

有一个C库(我无法更改)支持该类型的回调函数

void (*callback)(void *appContext, int eventid)
Run Code Online (Sandbox Code Playgroud)

我想设置一个C++函数作为回调.

具体来说,我有以下问题?

  1. 我是否需要在"extern C"块下声明回调函数?

  2. 成员函数是否需要是静态的才能成为回调函数?是否可以使用非静态成员函数?如果有,怎么样?什么时候建议使用非静态成员函数?

  3. 函数是否是模板函数是否重要?

  4. 非类C风格函数是否比类成员函数有任何优势?

我在旧的VC++编译器上尝试这些变体,它不支持最新的C++标准.但代码需要独立于平台,并且应该适用于大多数C++编译器.我想知道回调的推荐做法是什么?

Oak*_*tes 15

是否需要在extern"C"下声明回调函数?

没有.只有在不使用C语言的函数指针的情况下直接调用C++函数时,extern"C"才是必需的.如果使用函数指针,则不需要extern"C".

我可以使用非静态成员函数作为回调吗?

没有.类A的非静态成员函数具有与该指针对应的隐式第一参数.

我可以使用静态成员函数作为回调吗?

是的,只要签名与回调的匹配即可.

函数是否是模板函数是否重要?

否,只要实例化模板的签名与回调匹配,模板函数就可以用作回调.


Jon*_*ood 6

如果您的成员函数是静态的,这应该有效.

  • 只要该成员是静态的,调用约定是相同的,并且参数列表匹配它将起作用. (2认同)

Fer*_*cio 6

假设appContext是一个不透明的指针,您传递给进行回调的函数,您可以获得对特定对象的成员函数的回调,如下所示:

class myclass {

  void do_something() {
     // call function making the callback using _event_handler
     // as the callback function and the "this" pointer as appContext
  }

  // make sure the raw callback uses the correct calling convention (cdecl, stdcall, etc.)
  static void _handle_event(void* appContext, int eventid) {
    // forward the event to the actual object
    static_cast<myclass *>(appContext)->handle_event(eventid);
  }

  void handle_event(int eventid) {
     // do object-specific event handling
  }

};
Run Code Online (Sandbox Code Playgroud)

几个答案提到extern "C"了一个要求.这完全是错误的. extern "C"只有在直接从C++调用C函数时才需要.它用于告诉C++编译器"在为此函数生成符号名时不应用名称修改".您正在将C++函数指针传递给C函数.只要调用约定匹配,它就可以正常工作.函数的名称从不涉及.