Использовать обратные вызовы в ардуино с указателями на функции (будут ли функции сохраняться в памяти?)
Когда я изучал Arduino (микроконтроллеры, C++ и т. д.), я понял, что память очень ограничена. Я уже понимаю, как работает память, когда речь идет о переменных. Но я не понимаю, как работает память, когда речь идет о функциях. Поскольку я поддерживаемый разработчик, я стараюсь держаться подальше от прерываний и вместо этого использовать функции обратного вызова. Еще одна причина, по которой я предпочитаю использовать функции обратного вызова, заключается в том, что мне нравится интегрированная среда разработки Visual Studio. Я создаю свою основную функциональность любого проекта, который я создаю, на проекте C++, предназначенном для Windows. Как только мои алгоритмы/логика работают так, как я хочу, я ссылаюсь на эти библиотеки на Arduino.
В любом случае я использую лямбда-выражения для передачи функций в мои вспомогательные библиотеки. Таким образом, я не использую функцию задержки для ожидания ответа и всегда прослушиваю события. В основном мой вопрос заключается в том, правильно ли иметь такой код (функция SendEvent):
/* MyRadioLibrary.h */
// Я не включаю весь код `MyRadioLibrary`, потому что это затрудняет
// понять, о чем я спрашиваю. Вместо этого я постараюсь использовать много псевдокода. Разрешите
// узнайте, хотите ли вы, чтобы я опубликовал код в качестве редактирования.
class MyRadioLibrary
{
public:
static void SendEvent(int typeOfEvent, void(*onEventCompleted)(bool x))
{
// у меня есть массив указателей на функции
void(*onEventCompletedBuffer[10])(bool x);
// Я ставлю это событие в очередь с помощью вспомогательного класса очереди
// Отправить событие ....
// СЕЙЧАС ЖДЕМ ОТВЕТА, ПОСКОЛЬКУ ОБРАТНЫЙ ВЫЗОВ УЖЕ СОХРАНЕН
}
static void loop() {
// прослушивание радиосообщений
if(radio.available()){
// получаем ответ
// удалить указатель из очереди для обратного вызова
// выполнить обратный вызов
}
}
};
И мой скетч Arduino содержит этот код:
#include <MyRadioLibrary.h>
void setup() {
// установка пинов и т.д..
}
void loop()
{
if (isButton1Pressed())
{
MyRadioLibrary::SendEvent(1, [](bool didEventCompletedSuccessfully) {
if (didEventCompletedSuccessfully)
{
// включить зеленый светодиод
}
else {
// включаем красный светодиод
}
});
}
else if (isButton2Pressed())
{
MyRadioLibrary::SendEvent(2, [](bool didEventCompletedSuccessfully) {
// функция обратного вызова
});
}
MyRadioLibrary::loop(); // прослушивание ответных событий. Когда мы получим один пожарный ответный звонок.
}
Теперь вопрос
Когда я вызываю функцию SendEvent
, я передаю две вещи (1) целое число и (2) указатель на функцию, которая является обратным вызовом. Целое число (1) передается как значение, и оно будет частью стека функции SendEvent
. Указатель (2) будет храниться в массиве указателей. А как насчет лямбда-функции? где она будет храниться? Должен ли я вместо использования лямбда-функции объявить эти функции в глобальной области видимости и передать глобальную функцию вместо лямбда-выражения? Буду ли я рисковать тем, что указатель (2) будет указывать на функцию, которой больше не существует, если я буду использовать этот способ кодирования?
@Tono Nam, 👍0
Обсуждение1 ответ
Лучший ответ:
Ваши функции не перестанут существовать. Весь код в скомпилированном и связанном образе кода загружается в память кода (Flash) и остается там на протяжении всего выполнения, сбросов и циклов включения, пока поверх него не будет загружено другое изображение.
Не путаете ли вы указатели на функции с указателями на локальные переменные функции, которые занимают оперативную память, в частности внутри кадра стека функции, который является временным, создается и "уничтожается" по мере того, как функция вызывается и возвращается, и последующие кадры стека не обязательно будут создаваться в одном и том же месте.
- Как использовать лямбда-функции в Arduino?
- Передача нестатической функции-члена с помощью bind
- Вызов функций одного класса из другого класса — Обратный вызов
- Обратный вызов родительского класса из дочернего класса
- Использование лямбд в качестве функций обратного вызова
- Массив функций
- Как написать эффективные функции обратного вызова на Teensy 4.0?
- C++ против языка Arduino?
Насчет «_передать глобальную функцию вместо лямбда_»: после того, как она переведена в машинный код, уже не имеет значения, лямбда это или обычная функция., @Edgar Bonet