Как написать эффективные функции обратного вызова на Teensy 4.0?
Я рассматриваю возможность рефакторинга своего кода путем реализации функций обратного вызова, чтобы иметь возможность повторно использовать абстрактную логику других функций/классов.
Однако я чувствую, что мне нужно больше узнать об ограничениях функций обратного вызова во встроенных системах, таких как Teensy 4.0, которую я использую. Причина, по которой я спрашиваю, заключается в том, что - если я правильно информирован - std::function не рекомендуется использовать во встроенных системах из-за накладных расходов на память. Другая причина вопроса заключается в том, что функции, которые я хочу использовать для обратного вызова, могут привести к нарушению принципа сокращения функций обратного вызова.
Я просмотрел главу, посвященную принципам встроенного программирования, в книге Страуструпа «Программирование: принципы и практика использования C++». К сожалению, он не дает советов по функциям обратного вызова конкретно для встраиваемых систем.
Я понимаю, что могу просто положиться на метод проб и ошибок с использованием указателей на функции, но решил, что мне хотелось бы попросить вашего опыта и совета, прежде чем переписывать большую часть кода. Другими словами, я прошу хороших принципов и рекомендаций.
@Erik, 👍0
Обсуждение1 ответ
Я довольно интенсивно использовал обратные вызовы на Arduino Mega 2560,
для управления сообщениями RS-485. На этой плате примерно в 8 раз меньше флэш-памяти
и в 128 раз меньше оперативной памяти, чем у вашего Teensy. Однако, поскольку ядро AVR
не поддерживает std::function
, я использовал старую добрую идиому C для определения
обратные вызовы:
void MyClass::register_callback(
void (*callback)(some_type some_data, void *callback_data),
void *callback_data);
Вызывающая сторона должна правильно упаковать все состояние, необходимое
обратный вызов в struct
и передайте указатель на эту struct
в качестве
последний аргумент register_callback()
. Класс запишет как
указатель функции и указатель void*
. Когда ожидаемое событие
случается, класс вызывает обратный вызов, передавая ему сохраненный void*
как
его последний аргумент. Затем обратный вызов приводит этот указатель к указателю на
ожидаемую struct
, и теперь она может получить доступ к нужному состоянию.
Да, это немного неуклюже, но это проверенный и верный способ решения проблем. состояние обратного вызова на простом C. И стоимость незначительна, особенно для вашего доска, у которой на порядки больше ресурсов, чем у моей Меги.
Если вас пугает стоимость std::function
, я предлагаю вам
реализовать простой пример обратного вызова, используя этот метод, а затем использовать
std::function
, и вы сравниваете использование памяти. Если стоимость
std::function
оказывается важным, вы всегда можете перейти к C
способ. Я подозреваю, что с std::function
все будет в порядке, и на самом деле это нечто большее.
удобнее, чем обрабатывать указатель функции и состояние отдельно
аргументы.
Интересно, я посмотрю. Спасибо за ваш ответ!, @Erik
- C++ Undefined reference to 'Class:Function()'
- Передача нестатической функции-члена с помощью bind
- Вызов функций одного класса из другого класса — Обратный вызов
- Альтернатива опросу флага прерывания из основного цикла?
- Обратный вызов родительского класса из дочернего класса
- Невозможно отобразить строку chr с помощью Wire.read() и u8g2.drawStr().
- Использовать обратные вызовы в ардуино с указателями на функции (будут ли функции сохраняться в памяти?)
- Что не так с моим EEPROM?
Я часто использую обратные вызовы во встроенных системах на гораздо менее функциональных микроконтроллерах, чем Cortex (328p f/ex). Накладные расходы на вызовы незначительны — вызов через указатель вместо прямого вызова. На этой странице есть [руководство по обратным вызовам в Teensy](https://github.com/TeensyUser/doc/wiki/Callbacks)., @JRobert
Должны ли ваши обратные вызовы переносить состояние (т. е. быть объектами-функторами, содержащими данные), или вы просто будете использовать голые функции (или лямбда-выражения без захвата)?, @Edgar Bonet
@EdgarBonet Сразу пришло в голову, что это в основном будут голые функции, но возможно, мне понадобятся и другие типы вариантов использования., @Erik