Non-capturing case
As commenters point out, a lambda implicitly converts into a function pointer of the appropriate type, so we can just write:
auto my_lambda = [](void* data) { /* do stuff here */};
register_callback(my_lambda, get_pointer_to_data());
and this will compile. Don't forget to check the return value though :-)
Capturing case
Here's what I'm doing at the moment, but I suspect it's sub-optimal.
First I make sure that the lambda captures everything that it needs so that it is itself invokable with no parameters (so that it actually does not take a void*
like a callback is supposed to). Then I use this code:
template <typename Invokable>
void callback_adapter(void *invokable_on_heap)
{
auto retyped_callback = std::unique_ptr<Invokable>{
reinterpret_cast<Invokable*>(invokable_on_heap)
};
(*retyped_callback)(std::forward<Ts>(parameters)...);
// Note: invokable_on_heap will be delete'd
}
template <typename Invokable>
void register_invokable_as_callback(Invokable callback_) {
Invokable* invokable_on_the_heap = new Invokable(std::move(callback_));
register_callback(&callback_adapter<Invokable>, invokable_on_the_heap);
}
Note: With this approach, the callback can only be called once. It can be adapted to the case of a callback which needs to be called many times, with deallocation upon de-registration / destruction of whatever the callbacks are called for.