Working with std::function on C libraries

2019-08-06 05:24发布

I have a C library function with the following signature,

void register_callback(void (*callback)(int, void*), void* args);

What is the best way to get this to work with, if I have a callback of the form,

std::function<void(int)>?

2条回答
Rolldiameter
2楼-- · 2019-08-06 05:44
std::function<void(int)> bob;
register_callback( [](int x, void* pbob){
  auto& bob = *static_cast<std::function<void(int)>*>(pbob);
  bob(x);
}, &bob );

this remains valid for as long as the variable bob does.

A copy of bob is not enough, the actual instance of bob that we took a pointer to in the register_callback call has to live long enough.

If this is difficult, consider a smart pointer wrapping said std::function and doing a pointer to the stored std::function.

There will be modest overhead in the above, in that we dispatch over a function pointer, then over the equivalent of a vtable, then inside the std::function again.

What is going on above is that I make a stateless lambda to convert the void* args into a pointer-to-std::function, and invoke that std::function with the int. Stateless lambdas can convert to function pointers implicitly.

查看更多
Viruses.
3楼-- · 2019-08-06 05:45

With:

class CallBack
{
public:
    explicit CallBack(std::function<void(int)> f) : f(f) {}

    static void to_c_api(int a, void* that)
    {
        reinterpret_cast<CallBack*>(that)->f(a);
    }
private:
    std::function<void(int)> f;
};

You may then do

CallBack callback; // should live longer than the calls
void register_callback(CallBack::to_c_api, &callback);
查看更多
登录 后发表回答