Здесь я выполняю миссию спровоцировать аневризму у хардкорных разработчиков микроконтроллеров C/ASM. На этом фронте несколько месяцев назад я опубликовал первую статью в серии, в которой объясняется метод использования магии шаблонов C++ с небольшим количеством наследования для архивирования истинно типобезопасных и проверенных контейнеров во время компиляции без использования динамических выделение памяти.
В этой статье я объясню, как использовать эти контейнеры для использования классов Delegate и Signal, которые можно использовать со следующими требованиями:
- нет кучи
- без исключений
- нет внешних библиотек
- C++x03
Все эти требования необходимы, чтобы иметь возможность втиснуть класс в микроконтроллер.
В этот момент, возможно, вы спросите: «Но почему?, почему во имя всего хорошего я буду использовать такую штуку во встраиваемом устройстве?
Для микроконтроллера с оперативной памятью 1 КБ, которому нужно только следить за уровнем напряжения и переключать PIN-код по какой-либо причине, я бы сказал, что вам понадобится только компилятор C для вашей архитектуры, но с появлением архитектуры ARM Cortex-M мы наблюдая рост гигантов, таких как семейство микроконтроллеров STM32H7, с большим количеством периферийных устройств, которые вам понадобятся, и большим объемом памяти, которую вы сможете использовать на простом C без каких-либо проблем.
С этими микроконтроллерами вы сможете выполнять несколько задач одновременно, используя ОС реального времени и должным образом расширять свое приложение, не впадая в спагетти-код и безумие, вам потребуются высокоуровневые абстракции, чтобы сохранить модульность кода. и с минимальной площадью поверхности между модулями, и чтобы действительно использовать всю мощь и универсальность микроконтроллеров нового поколения.
Практически невозможно масштабировать ваше приложение, если в его основе лежат макросы и простые обратные вызовы функций C, которые, конечно, являются примерами превосходной кодовой базы C, такой как ядро Linux, но давайте смотреть правде в глаза, средний разработчик не так квалифицирован и дисциплинирован, как разработчик ядра Linux.
Теперь вы могли бы сказать: Но ведь и в C можно реализовать высокоуровневые абстракции, посмотрите на библиотеки «GTK!!!»
Итак, проект GTK представляет собой отличный набор библиотек для разработки приложений с графическим интерфейсом на C, и почти никто не использует его на простом C. Большинство разработчиков используют привязки к другим языкам для взаимодействия с GTK, такие как PyGTK или Vala, из-за церемония / боль использования GTK в простом C влечет за собой.
Используйте Qt,….кашель, кашель……используйте Qt.
делегат
В приведенном ниже коде показан пример класса Delegate, связывающего каждый тип… «вещи»…. которые могут быть ограничены в C++.
Класс может связываться:
- глобальная функция
- метод статического класса
- метод класса
Ограничено только одним методом за раз и нулем (void) или одним параметром (передается по значению). В классе есть оператор вызова функции (), перегруженный для вызова связанного метода (если он есть). Он спроектирован так, чтобы быть наименее навязчивым, и если он вызывается без привязки к методу, он просто ничего не делает. Если у него есть связанный метод, и вы хотите связать другой, он позволит вам это сделать. Также имеет служебные функции, такие как isBinded(), isUnbinded() и clear(), и они делают то, что, по вашему мнению, должны делать.
Сигнал
Класс Signal, который многое заимствует из концепции сигнал и слоты Qt, я большой поклонник Qt, для меня это единственный способ программировать на C++ без слез.
Этот класс содержит внутренний массив делегатов, размер которого необходимо указать во время компиляции.
В примере создаются два сигнала, один из которых может быть связан с четырьмя функциями, а другой имеет параметр int и может быть связан с двумя функциями.
Подключенные методы/функции вызываются в том же порядке, в котором они подключены. Соединения могут быть перезаписаны, они должны быть отключены явным образом.
Помните, что эти классы предназначены для использования в среде, где никакие объекты никогда не уничтожаются, поэтому вы должны быть уверены, что экземпляр, к которому подключен de signal, жив, когда вызывается метод notify(). Если подключенный экземпляр будет уничтожен, а сигнал сработает, тогда… Kaput!!
Реализация Delegate and Signal Pattern упростит разработку приложений микроконтроллеров, которые должны выполнять несколько задач и, что, возможно, более важно, должны поддерживаться в течение нескольких лет.
Эти два класса являются частью иерархической библиотеки конечного автомата, которую можно найти здесь.
Следующая статья в этой серии будет о том, что такое иерархическая библиотека конечных автоматов и как и какие проблемы она решает.
Переиздано с linkedin.