arduino — C ++: закрытие для передачи функции-члена как обычного указателя на функцию

Я пытаюсь вызвать функцию-член внешней библиотеки, которая принимает указатель на функцию в качестве параметра:

Timer::every(unsigned long period, void (*callback)(void));

Но, к сожалению, параметр, который я хочу передать, является функцией-членом:

void MyClass::the_method_i_want_to_pass(void);

Поскольку я программирую для ATMega под Arduino (AVR), поддержка c ++ 11 ограничена. Мой первый подход вызывает ошибку типа:

void MyClass::the_method_i_want_to_pass() {...}

MyClass::MyClass() {
// constructor

Timer *timer = new Timer();
timer->every(500, [this](){this->the_method_i_want_to_pass();})
}

Выход компилятора:

предупреждение: предупреждение: лямбда-выражения доступны только с -std = c ++ 11 или -std = gnu ++ 11 [включено по умолчанию]

ошибка: нет соответствующей функции для вызова call Timer :: every (int, MyClass :: MyClass () :: __ lambda0) ’

  1. Есть ли другие / лучшие решения?
  2. Относительно моего текущего подхода: (Как) можно передать ссылку на лямбду, когда требуется указатель на функцию?
  3. Как я могу узнать, поддерживает ли Arduino / AVR эти лямбды (см. «Предупреждение»)?

3

Решение

Ваша основная проблема ваша Timer библиотека написана плохо: надо брать void(*)(void*), void* по крайней мере.

Без pvoid или его эквивалента вы не можете передать любое состояние, кроме адреса в коде выполнения, для запуска процедуры. Как метод также reuuuers this указатель, вам не повезло.

Теперь, если ваш экземпляр MyClass это одиночка, вы можете получить this откуда-то еще

В противном случае вам нужно создать собственное глобальное состояние, которое позволяет отображать конкретный обратный вызов в какое-то состояние. Если у вас есть ограниченное количество MyClass и другие потребители TimerВы можете иметь несколько фиксированных функций, и они могут хранить свое дополнительное состояние во всем мире.

Это все взломать. Что следует, хуже.

Напишите динамическую библиотеку с некоторым глобальным состоянием и void() интерфейс. Когда вы добавляете обратный вызов, продублируйте эту динамическую библиотеку, измените ее глобальное состояние во время выполнения, запишите ее как библиотеку с другим именем, загрузите ее и передайте функцию чистого обратного вызова вашей Timer учебный класс.

Или сделайте эквивалент без библиотеки, вручную написав машинный код и пометив страницы как исполняемые.

Это все плохие решения. Что приводит меня к хорошему: найди лучшее Timer, Если они испортили что-то такое простое, остальная часть библиотеки, вероятно, тоже плохая.

1

Другие решения


По вопросам рекламы [email protected]