简体   繁体   English

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

[英]Replacing boost-signals2 with C++11 signals

I'm a research programmer developing autonomy systems for unmanned vehicles and I'm in the middle of modifying some open source code from another project to make a driver for vehicle control.我是一名研究程序员,为无人驾驶车辆开发自主系统,我正在修改另一个项目的一些开源代码,以制作用于车辆控制的驱动程序。 The idea is to have a module that generally handles control that loads a vehicle-specific driver as a library, and the existing implementation uses boost::signals2 to bind the module function calls to the driver.这个想法是有一个模块,它通常处理加载特定于车辆的驱动程序作为库的控制,现有实现使用 boost::signals2 将模块函数调用绑定到驱动程序。 Since this is the only thing that it's currently using boost for, I'd like to remove the boost dependency and use C++ signals, but I'm having difficulty figuring out how to do that.由于这是它目前唯一使用 boost 的东西,我想删除 boost 依赖项并使用 C++ 信号,但我很难弄清楚如何做到这一点。

I've been trying to read up on boost::signals2 and C++ signals in general to see if I can just teach myself the principles and syntax: - 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 I think that I'm getting the concepts, but the implementation is confusing the tar out of me.我一直在尝试阅读 boost::signals2 和 C++ 信号,看看我是否可以自学原理和语法: - https://en.cppreference.com/w/cpp/utility/program/信号- https://testbit.eu/2013/cpp11-signal-system-performance - https://simmesimme.github.io/tutorials/2015/09/20/signal-slot我想我得到了概念,但实施让我迷惑了焦油。 The first and second resources that I posted make it look like C++ signals are built in to C++11, but the tutorial in the third link seems to define its own signal class and doesn't seem to use the syntax in the first at all.我发布的第一个和第二个资源使它看起来像 C++ 信号内置于 C++11,但第三个链接中的教程似乎定义了自己的信号类,并且似乎没有使用第一个中的语法全部。

It looks like other projects have done this before ( https://github.com/cinder/Cinder/issues/619 ), but I haven't been able to find any specific examples that show the before-and-after to compare - seeing an implementation is typically what clicks theory into place for me.看起来其他项目之前已经这样做了( https://github.com/cinder/Cinder/issues/619 ),但我一直无法找到任何显示前后对比的具体示例 -看到一个实现通常是我点击理论的地方。

From the driver library header file:从驱动程序库头文件:

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

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

From the driver cpp file:从驱动程序 cpp 文件:

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

From the module cpp:从模块 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 );
}

The driver declares a signal that it can use to send data up to the module that loads it, and that module then binds that signal to a function so that when that signal is called and data provided to it, the data goes to that function.驱动程序声明了一个信号,它可以用来将数据发送到加载它的模块,然后该模块将该信号绑定到一个函数,以便在调用该信号并向其提供数据时,数据将转到该函数。 I'm just trying to figure out how to accomplish the same thing without using Boost, which I guess means figuring out how to replace the boost::bind as well.我只是想弄清楚如何在不使用 Boost 的情况下完成同样的事情,我猜这意味着弄清楚如何替换 boost::bind 。 Any pointing in the right direction is much appreciated;任何指向正确方向的人都非常感激; I'm going to keep working on it and will post if I figure anything else out in case it's helpful to anyone going down the same road in the future.我将继续努力,如果我想出其他任何东西,我会发布,以防它对将来走同一条路的任何人都有帮助。

The problem here is that there are two related but different technologies that are both named signals. 这里的问题是有两种相关但不同的技术都是命名信号。

The signal constructs in <signal.h> and the corresponding <csignal> are signals in the POSIX sense and are related to error handling such as when the OS kills the program or a catastrophic internal error occurs. <signal.h>的信号结构和相应的<csignal>POSIX意义上的信号,与错误处理有关,例如当操作系统杀死程序或发生灾难性内部错误时。

Signals and slots such as Boost.signals2, Qt's signals/slots, etc. are a more general implementation of the observer pattern which allow one piece of code to offer a loosely coupled way for another piece of code to get a notification or callback when some event happens. 信号和插槽 (如Boost.signals2,Qt的信号/插槽等)是观察者模式的更通用的实现,它允许一段代码为另一段代码提供松散耦合的方式,以便在某些代码时获得通知或回调事件发生了。

The former is really a subset of the latter since POSIX signals are mostly related to error and termination events, whereas signals and slots in general also work for less ominous events like "a network packet has arrived!" 前者实际上是后者的一个子集,因为POSIX信号主要与错误和终止事件有关,而信号和时隙通常也适用于较少的不祥事件,如“网络数据包已到达!” or "the user clicked a button!" 或者“用户点击了一个按钮!”

I would not recommend trying to shoehorn a general signal-slot solution into the aged (and C-style) POSIX signals API. 我不建议尝试将一般信号槽解决方案用于老化(和C风格)POSIX信号API。

While there is no standard C++ signal/slot library, there is a variety of third-party libraries, as some of your links show. 虽然没有标准的C ++信号/插槽库,但是有一些第三方库,正如您的一些链接所示。 I wouldn't recommend rolling your own unless you have a compelling reason to reinvent the wheel. 除非你有令人信服的理由重新发明轮子,否则我不建议你自己滚动。 (If you must roll your own, std::function is the obvious starting point.) Boost's is a high-quality implementation, and since you're already using it, I would stick with that. (如果你必须自己动手, std::function是一个明显的起点。)Boost是一个高质量的实现,因为你已经在使用它,我会坚持这一点。 (Our rule of thumb at my company is, with all things being approximately equal, "std > Boost > Qt > other", but YMMV.) (我们公司的经验法则是,所有事情大致相同,“std> Boost> Qt> other”,但YMMV。)

If you just want to reduce the footprint of your Boost folder, Boost supplies BCP to do just that. 如果您只想减少Boost文件夹的占用空间,Boost会提供BCP来做到这一点。

Now that the C++ standard has made such progress, I am more reluctant than ever to use Boost headers.现在 C++ 标准已经取得了这样的进步,我比以往任何时候都更不愿意使用 Boost 头文件。 While browsing github, I came across this alternative to Boost Signals2 :在浏览 github 时,我遇到了 Boost Signals2 的替代方案:

https://github.com/cpp11nullptr/lsignal https://github.com/cpp11nullptr/lsignal

Although its documentation could be improved (not a full example of use in the README), it seems simple and efficient.虽然它的文档可以改进(不是 README 中使用的完整示例),但它看起来简单而高效。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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