如何将 C++ lambda 传递给需要函数指针和上下文的 C 回调?

2021-12-23 00:00:00 lambda c c++ c++11

我正在尝试在使用标准函数指针+上下文范例的 C-API 中注册回调.这是 api 的样子:

I'm trying to register a callback in a C-API that uses the standard function-pointer+context paradigm. Here's what the api looks like:

void register_callback(void(*callback)(void *), void * context);

我真正想做的是能够将 C++ lambda 注册为回调.此外,我希望 lambda 是一个已捕获变量(即不能转换为直接无状态的 std::function)

What I'd really like to do is be able to register a C++ lambda as the callback. Additionally, I want the lambda to be one that has captured variables (ie. can't be converted to a straight stateless std::function)

我需要编写什么样的适配器代码才能将 lambda 注册为回调?

What kind of adapter code would I need to write to be able to register a lambda as the callback?

推荐答案

简单的方法是将 lambda 粘贴到一个 std::function 中,并保存在某处.可能它是在堆上分配的,并且仅被注册到接受回调的实体的 void* 引用.回调将只是一个像这样的函数:

The simple approach is to stick the lambda into a std::function<void()> which is kept somewhere. Potentially it is allocated on the heap and merely referenced by the void* registered with the entity taking the callback. The callback would then simply be a function like this:

extern "C" void invoke_function(void* ptr) {
    (*static_cast<std::function<void()>*>(ptr))();
}

请注意,std::function 可以保存具有状态的函数对象,例如,具有非空捕获的 lambda 函数.您可以像这样注册回调:

Note that std::function<S> can hold function objects with state, e.g., lambda functions with a non-empty capture. You could register a callback like this:

register_callback(&invoke_function,
  new std::function<void()>([=](){ ... }));

相关文章