我是一名研究程序员,正在为无人驾驶车辆开发自动驾驶系统,我正在修改另一个项目的一些开源代码,以使其成为车辆控制的驾驶员。其思想是拥有一个模块,该模块通常处理加载特定于车辆的驱动程序作为库的控制,现有实现使用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++11内置的C++信号,但是第三个链接中的教程似乎定义了它自己的信号类,并且似乎根本没有使用第一个中的语法。
看起来其他项目以前也这样做过(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。任何指向正确方向的人都非常感激;我将继续努力,如果我发现了其他问题,我会发表文章,以防对将来走上同样道路的任何人有所帮助。
发布于 2019-06-04 21:23:02
这里的问题是,有两种相关但不同的技术,都是命名信号。
<signal.h>和相应的<csignal>中的信号构造是signals in the POSIX sense的,并且与错误处理相关,例如当OS终止程序或发生灾难性的内部错误时。
诸如Boost.signals2、Qt的信号/槽等Signals and slots是观察者模式的更一般的实现,它允许一段代码为另一段代码提供一种松散耦合的方式,以便在某个事件发生时获得通知或回调。
前者实际上是后者的一个子集,因为POSIX信号主要与错误和终止事件有关,而信号和时隙通常也适用于不太危险的事件,如“网络数据包已到达!”或者“用户点击了一个按钮!”
我不建议将一个通用的信号槽解决方案硬塞到过时的(和C风格的) POSIX信号API中。
虽然没有标准的C++信号/槽库,但有各种第三方库,如您的一些链接所示。除非你有一个令人信服的理由重新发明轮子,否则我不建议你自己滚动。(如果您必须使用自己的代码,那么std::function是一个显而易见的起点。)Boost的是一个高质量的实现,既然你已经在使用它了,我会坚持使用它。(我们公司的经验法则是,在所有条件大致相同的情况下,"std > Boost > Qt > other",但YMMV。)
如果你只是想减少Boost文件夹的占用空间,Boost提供的BCP就可以做到这一点。
发布于 2021-10-22 09:28:18
现在C++标准已经取得了这样的进步,我比以往任何时候都更不愿意使用Boost头。在浏览github时,我遇到了这个提升Signals2的替代方案:
https://github.com/cpp11nullptr/lsignal
尽管它的文档可以改进(不是在自述文件中使用的完整示例),但它似乎简单有效。
https://stackoverflow.com/questions/56444592
复制相似问题