Michael Bishop Michael Bishop - 3 months ago 20
C Question

How can I pass a C++ lambda to a C-callback that expects a function pointer and a context?

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


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
)

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

Answer

The simple aporoach 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 line this:

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

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()>([=](){ ... }));