将 std::function<void ()> 转换为 void (*)()

时间:2021-01-20 04:15:06

标签: c++ raspberry-pi c++17 std-function

所以我在 C++ 中有一个成员函数,它接受一个 std::function<void>,我想把它传递给一个 WiringPi 函数:

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

我收到错误 cannot convert ‘std::function<void()>’ to ‘void (*)()’ in initialization。我在网上查看过,我只找到了有一百行指针和引用转换并且不在 pi 上编译的东西。在这里寻找任何帮助。我应该一直使用 void (*)() 吗?这似乎是错误的方法。我可以找到很多关于将 void (*)() 转换为 std::function<void> 而不是相反的方法..

PS:我是 C++ 的菜鸟。我的主要语言是 C# 和其他一些高级语言,所以仍在学习这门语言,但不确定我在这里遗漏了什么..

2 个答案:

答案 0 :(得分:1)

<块引用>

将 std::function 转换为 void (*)()

你不能。

<块引用>

我应该一直使用 void (*)() 吗?

是的。

从技术上讲,使用 std::function 是可行的,但您必须依赖全局状态,而且使用 std::function 的好处可能不值得付出这样的代价。

<块引用>

这似乎是错误的方法。

不是,因为您使用的 API 存在限制。

答案 1 :(得分:1)

这是一个如何做到的例子。

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

很多错别字,可能还有语法错误,但我希望这个想法很清楚。

我们制作了一个固定大小的函数指针和标准函数的全局数组。函数指针知道它们的索引,因此它们查找 std 函数并运行它。注册查找未使用的 std 函数,填充它,并返回函数指针。

保持 N 低,因为它会占用可执行代码内存和运行时内存。但是,如果它太低,则回调将用完。