c++ - 用 C++11 信号替换 boost-signals2

标签 c++ boost signals boost-signals2

我是一名为无人驾驶车辆开发自治系统的研究程序员,我正在修改另一个项目的一些开源代码以制作用于车辆控制的驱动程序。这个想法是拥有一个模块,该模块通常处理将特定于车辆的驱动程序加载为库的控制,并且现有的实现使用 boost::signals2 将模块函数调用绑定(bind)到驱动程序。由于这是它目前唯一使用 boost 的东西,我想删除 boost 依赖并使用 C++ 信号,但我很难弄清楚如何做到这一点。

我一直在尝试通读 boost::signals2 和 C++ 信号,看看我是否可以自学原理和语法: - https://en.cppreference.com/w/cpp/utility/program/signal - https://testbit.eu/2013/cpp11-signal-system-performance - https://simmesimme.github.io/tutorials/2015/09/20/signal-slot 我认为我已经理解了这些概念,但是实现让我感到困惑。我发布的第一个和第二个资源使它看起来像 C++ 信号内置于 C++11,但第三个链接中的教程似乎定义了它自己的信号类并且似乎没有使用第一个中的语法全部。

看起来其他项目之前已经这样做了(https://github.com/cinder/Cinder/issues/619),但我一直没能找到任何具体的例子来比较之前和之后——看到一个实现通常是点击理论的原因给我的位置。

来自驱动库头文件:

class InterfaceBase
{
   InterfaceBase( const Config& cfg );
   virtual ~InterfaceBase() { }

   boost::signals2::signal<void (const InterfaceState& state)> signal_state_change;
}

来自驱动cpp文件:

void InterfaceBase::check_change_state()
{
   if( state_ != previous_state )
   {
      signal_state_change( state_ );
   }
}

来自模块 cpp:

template<typename Signal, typename Slot>
   void connect( Signal* signal, Slot slot )
{ signal->connect( slot ); }

template<typename Signal, typename Obj, typename A1>
   void connect( Signal* signal, Obj* obj, void( Obj::*mem_func )( A1 ))
{ connect( signal, boost::bind( mem_func, obj, _1 )); }

Interface::Interface()
{
   if( cfg_.has_driver_lib_path() )
   {
      driver_library_handle = dlopen( cfg_.driver_lib_path().c_str(), RTLD_LAZY );
      if( !driver_library_handle )
      {
         exit( EXIT FAILURE );
      }
   }
   else
   {
      exit( EXIT_FAILURE );
   }
   driver_ = load_driver( &cfg_ );

   connect( &driver_->signal_state_change, this, &Interface::ProcessStateChange );
}

驱动程序声明一个信号,它可以使用该信号将数据发送到加载它的模块,然后该模块将该信号绑定(bind)到一个函数,以便在调用该信号并向其提供数据时,数据将转到那个功能。我只是想弄清楚如何在不使用 Boost 的情况下完成同样的事情,我想这也意味着弄清楚如何替换 boost::bind。非常感谢任何指向正确方向的信息;我将继续努力,如果我发现任何其他问题,我会发布,以防它对将来走同一条路的任何人有帮助。

最佳答案

这里的问题是有两种相关但不同的技术,它们都是命名信号。

信号构造在<signal.h>中和相应的<csignal>signals in the POSIX sense并且与错误处理有关,例如当操作系统终止程序或发生灾难性内部错误时。

Signals and slots例如 Boost.signals2,Qt 的信号/槽等是观察者模式的更通用的实现,它允许一段代码为另一段代码提供一种松散耦合的方式,以便在某些事件发生时获得通知或回调。

前者实际上是后者的一个子集,因为 POSIX 信号主要与错误和终止事件相关,而信号和槽通常也适用于不太严重的事件,例如“网络数据包已到达!”或“用户点击了一个按钮!”

我不建议尝试将通用信号槽解决方案硬塞进陈旧的(和 C 风格的)POSIX 信号 API。

虽然没有标准的 C++ 信号/插槽库,但有多种第三方库,如您的一些链接所示。除非您有令人信服的理由重新发明轮子,否则我不建议您自己动手。 (如果您必须自己动手, std::function 显然是起点。)Boost 是一个高质量的实现,并且由于您已经在使用它,所以我会坚持使用它。 (我们公司的经验法则是,在所有条件都大致相等的情况下,“std > Boost > Qt > other”,但 YMMV。)

如果您只想减少 Boost 文件夹的占用空间,Boost 提供 BCP做到这一点。

关于c++ - 用 C++11 信号替换 boost-signals2,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56444592/

相关文章:

c++ - std::result_of 和 decltype 之间的区别

c++ - 无法正确构建 Boost

c - 如何通过信号重复重启程序

c - 在 waitpid 中处理 SIG_CHLD

c++ - 是否可以让指针指向第一个指针指向的变量?

c++ - 来自 C++11 中 C99 的 fenv.h

c++ - 在 openMPI、C++ 中发送 ImageMagick 对象

c++ - 使用空元素 boost Json

c++ - 在 std::string 和 std::wstring 之间转换的多平台方式

c - 忽略信号的不同方法?