简体   繁体   中英

Convert std::function<void ()> to void (*)()

So I have a member function in C++ that takes in an std::function<void> and I want to pass this into a wiringPi function:

void my_class::on_change(std::function<void()> func) const
{
    wiringPiISR(
        wiring_pi_pin_number_,
        INT_EDGE_BOTH,
        func);
}

I am getting the error cannot convert 'std::function<void()>' to 'void (*)()' in initialization . I have looked online and I am only finding things that have a hundred lines of pointer and reference casting and do not compile on a pi. Looking for any help here. Should I be using void (*)() all the way up the stack? This seems like the wrong approch. I can find plenty about converting a void (*)() to a std::function<void> but not the other way around..

PS: I am a noob at c++. My main language is C# and some other higher languages so still learning this one and not sure what I am missing here..

Convert std::function<void ()> to void (*)()

You cannot.

Should I be using void (*)() all the way up the stack?

Yes.

Technically using std::function could work but you'd have to rely on global state and the benefits of using std::function may not be worth that cost.

This seems like the wrong approch.

It's not, given the limitations of the API that you use.

Here is an example of how you can do it.

template<class Sig> using pfunc_t=Sig*;
template<class Sig>
struct callback_entry{
  pfunc_t<Sig> pf = nullptr;
  std::function<Sig> f;
};
trmplate<class Sig, std::size_t N>
using callback_table = std::array< callback_entry<Sig>, N >;

template<class Sig, std::size_t N, callback_table<Sig,N>* ptable, class R, class...Args, std::size_t...Is>
callback_table<Sig,N> make_table( std::index_sequence<Is...> ){
  return {{
    {[](Args... args)->R{ return (*ptable)[Is].f(std::forward<Args>(args)); }}...
  }};
}

template<std::size_t N, class R, class...Args>
callback_table<R(Args...), N> callbacks = make_table<R(Args...), N, &callbacks<N,R,Args...>, R, Args...>(std::make_index_sequence<N>{});

template<std::size_t N, class R, class...Args>
pfunc_t<R(Args...)> register_callback( std::function<R(Args...)> f ){
  for(auto&& entry:callbacks<N,R,Args...>){
    if (entry.f) continue;
    entry.f=std::move(f);
    return entry.pf;
  }
}
template<std::size_t N, class R, class...Args>
void recycle_callback( pfunc_t<R(Args...)> pf ){
  for(auto&& entry:callbacks<N,R,Args...>){
    if (pf!=entry.pf) continue;
    entry.f=nullptr;
  }
}

lots of typos, and probably syntax errors, but I hope the idea is clear.

We make a global array of function pointers and std functions of fixed size. The function pointers know their index, so they look up the std function and run it. Registering looks for an unused std function, populates it, and returns the function pointer.

Keep N low, as it eats up both executable code memory and runtime memory. If it is too low you run out of callbacks however.

To convert std::function<void()> to void(*)() use the std::function::target<>() function.

The target function returns a pointer to the stored callable function target, as shown in code below.

void f()
{
    cout << "f()" << endl;
}

void f1(void(*p)())
{
    p();
}

int main() {
    
    // Convert std::function<void()> to void(*)()
    
    std::function<void()> fp = &f;
    auto p1 = fp.target<void(*)()>();
    void (*p2)() = *p1;
    p2();
    
    f1(p2);
}

Output:

f()

f()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM