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. 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.
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. 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.
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.
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:
void InterfaceBase::check_change_state()
{
if( state_ != previous_state )
{
signal_state_change( state_ );
}
}
From the module 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. 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.