将升压信号2替换为 C++11 信号

Replacing boost-signals2 with C++11 signals

本文关键字:信号 C++11 替换      更新时间:2023-10-16

我是一名研究程序员,为无人驾驶车辆开发自主系统,我正在修改另一个项目中的一些开源代码,以制作车辆控制的驱动程序。这个想法是有一个模块,该模块通常处理将特定于车辆的驱动程序加载为库的控制,并且现有实现使用 boost::signals2 将模块函数调用绑定到驱动程序。由于这是它目前唯一使用 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 );
}

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

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

<signal.h>中的信号结构和相应的<csignal>是POSIX意义上的信号,与错误处理有关,例如当操作系统杀死程序或发生灾难性内部错误时。

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

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

我不建议尝试将通用信号槽解决方案硬塞到老化(和 C 型)POSIX 信号 API 中。

虽然没有标准的C++信号/插槽库,但有各种各样的第三方库,如您的一些链接所示。我不建议自己滚动,除非你有令人信服的理由重新发明轮子。(如果你必须自己动手,std::function是显而易见的起点。Boost是一个高质量的实现,既然你已经在使用它,我会坚持下去。(我们公司的经验法则是,在所有条件大致相同的情况下,"std> Boost> Qt>其他",但 YMMV。

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

现在C++标准已经取得了这样的进步,我比以往任何时候都更不愿意使用 Boost 标头。在浏览 github 时,我遇到了这个 Boost Signals2 的替代方案:

https://github.com/cpp11nullptr/lsignal

尽管它的文档可以改进(不是自述文件中的完整示例),但它似乎简单而高效。