【问题标题】:Convert std::function<void ()> to void (*)()将 std::function<void ()> 转换为 void (*)()
【发布时间】:2021-01-20 04:15:06
【问题描述】:

所以我在 C++ 中有一个成员函数,它接收一个 std::function&lt;void&gt;,我想将它传递给一个 WiringPi 函数:

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

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

PS:我是 C++ 的菜鸟。我的主要语言是 C# 和其他一些高级语言,所以还在学习这门语言,不知道我在这里缺少什么..

【问题讨论】:

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


【解决方案1】:

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

你不能。

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

是的。

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

这似乎是错误的方法。

鉴于您使用的 API 的限制,它不是。

【讨论】:

    【解决方案2】:

    这里有一个例子来说明如何做到这一点。

    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 低,因为它会占用可执行代码内存和运行时内存。但是,如果它太低,您就会用完回调。

    【讨论】:

      【解决方案3】:

      要将std::function&lt;void()&gt; 转换为void(*)(),请使用std::function::target&lt;&gt;() 函数。

      目标函数返回一个指向存储的可调用函数目标的指针,如下代码所示。

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

      输出:

      f()
      
      f()
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-12-11
        • 2017-07-08
        • 2018-02-26
        • 2019-06-05
        • 2011-03-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多