Замена boost-сигналов2 на сигналы C ++ 11 - PullRequest
1 голос
/ 04 июня 2019

Я программист, занимающийся разработкой систем автономии для беспилотных транспортных средств, и сейчас я занимаюсь модификацией некоторого открытого исходного кода из другого проекта, чтобы сделать водителя для управления транспортным средством.Идея состоит в том, чтобы иметь модуль, который обычно обрабатывает элемент управления, который загружает драйвер для конкретного транспортного средства в виде библиотеки, а существующая реализация использует boost :: signal2 для привязки вызовов функций модуля к водителю.Поскольку это единственное, для чего в настоящее время используется повышение, я хотел бы удалить зависимость повышения и использовать сигналы C ++, но мне трудно понять, как это сделать.

Я былпытаясь прочитать о сигналах boost :: signal2 и 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 также.Любое указание в правильном направлении очень ценится;Я продолжу работать над этим и опубликую пост, если я что-нибудь выясню на случай, если это пригодится любому, кто пойдет тем же путем в будущем.

1 Ответ

6 голосов
/ 04 июня 2019

Проблема в том, что есть две связанные, но разные технологии, которые называются сигналами.

Сигнальные конструкции в <signal.h> и соответствующие <csignal> являются сигналами в смысле POSIX и связаны с обработкой ошибок, например, когда ОС убивает программу или катастрофической внутренней ошибкойпроисходит.

Сигналы и слоты , такие как Boost.signals2, сигналы / слоты Qt и т. Д., Являются более общей реализацией шаблона наблюдателя, который позволяет одному куску кода предлагать слабосвязанный способ длядругой фрагмент кода для получения уведомления или обратного вызова при возникновении какого-либо события.

Первый действительно является подмножеством последнего, поскольку сигналы POSIX в основном связаны с ошибками и событиями завершения, тогда как сигналы и слоты в целом также работаютдля менее зловещих событий типа "сетевой пакет прибыл!"или «пользователь нажал кнопку!»

Я бы не советовал пытаться использовать общее решение для сигнальных слотов в устаревшем (и в стиле C) API сигналов POSIX.

Пока естьнет стандартной C ++ библиотеки сигналов / слотов, есть множество сторонних библиотек, как показывают некоторые ваши ссылки.Я бы не советовал кататься самостоятельно, если у вас нет веских причин изобретать велосипед.(Если вам нужно бросить свой собственный, std::function является очевидной отправной точкой.) Boost - это высококачественная реализация, и, поскольку вы уже используете ее, я бы придерживался этого.(Наше эмпирическое правило для моей компании, при прочих равных условиях, «std> Boost> Qt> other», но YMMV.)

Если вы просто хотите уменьшить площадь своей папки Boost,Для этого просто добавьте BCP .

...