C ++ Как вызывать методы внутри класса как указатель на функцию для TaskScheduler - Arduino - PullRequest
0 голосов
/ 08 мая 2018

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

Я использую TaskScheduler Чтобы настроить все необходимое в классе, я хочу вызвать следующую функцию Нормальные примеры для arduino не используют классы, и я изо всех сил пытаюсь заставить это работать в моем рефакторированном коде.

void Weather::setup(std::shared_ptr<Scheduler> s ,int id, String appid, uint32_t interval) 
{
  ...
  weatherTask(interval, TASK_FOREVER, &Weather::updateWeatherCallback, *scheduler, true);
}

функция updateWeatherCallback также реализована в этом классе:

void Weather::updateWeatherCallback() {...}

Помимо использования приведенного выше кода, я попробовал несколько лямбда-вариантов, предложенных здесь на Stackoverflow, и просто следующее:

weatherTask(interval,TASK_FOREVER, [this](){this->updateWeatherCallback;},*scheduler,true);

Но я подумал, что мое понимание этих ответов на Stackoverflow не очень хорошее - это больше проб и ошибок, что затрудняет поиск «правильных ответов»

Некоторые подробности из TaskScheduler-Library:

typedef void (*TaskCallback)();
class Task {
  friend class Scheduler;
  public:
    INLINE Task(unsigned long aInterval=0, long aIterations=0, TaskCallback aCallback=NULL, 
       Scheduler* aScheduler=NULL, bool aEnable=false, TaskOnEnable aOnEnable=NULL, 
       TaskOnDisable aOnDisable=NULL);
...

Спасибо:)

Ответы [ 3 ]

0 голосов
/ 08 мая 2018

Хотя использование указателей на функции выше - старый способ сделать это, более новый способ - использовать объекты функций и библиотеку <functional>. См. здесь для обзора всей библиотеки, с примерами в std::function, дающим хороший учебник «Вот как это работает».

Также посмотрите на лямбды для этого типа вещей. Это также весьма полезно и может храниться в std::function.

0 голосов
/ 08 мая 2018

weatherTask хочет указатель функции, а не указатель на член. Возможный способ решить эту проблему - создать вспомогательную структуру и связать функцию с std::function.

#include <functional>

template <typename T>
struct Callback;

template <typename Ret, typename... Params>
struct Callback<Ret(Params...)> {
   template <typename... Args> 
   static Ret callback(Args... args) {                    
      func(args...);  
   }
   static std::function<Ret(Params...)> func; 
};

template <typename Ret, typename... Params>
std::function<Ret(Params...)> Callback<Ret(Params...)>::func;

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

Callback<void(void)>::func = std::bind(&Weather::updateWeatherCallback, this);
TaskCallback func = static_cast<TaskCallback>(Callback<void(void)>::callback);
weatherTask(interval, TASK_FOREVER, func, *scheduler, true);

Решение было представлено как ответ на этот вопрос. Поскольку я не могу комментировать, я решил предоставить это в качестве ответа.


В качестве альтернативы вы можете использовать функцию, похожую на батут. Поэтому вам потребуется хранить глобальный указатель на ваш Weather объект.

Weather global_ptr;

Тогда вы сможете создать weatherTask с помощью лямбда-функции.

weatherTask(interval, TASK_FOREVER, [](){global_ptr->updateWeatherCallback();}, *scheduler, true);
0 голосов
/ 08 мая 2018

Надеюсь, это поможет. Программы как данные: указатели функций

В вашем примере вы можете объявить класс погоды следующим образом:

class Weather {
   public:
      setup(std::shared_ptr<Scheduler> scheduler, int id, String appid, uint32_t interval);
      updateWeatherTask(uint32_t interval, <Your Const>, function callback_func, std::shared_ptr<Scheduler> scheduler, bool someVar);
}

Всякий раз, когда вы объявляете тело метода, попробуйте вызвать функцию callback_func внутри функции updateWeatherTask с соответствующими параметрами.

Обновление

Это всего лишь один из способов сделать это. Перейдите по ссылке, вы можете найти различные простые способы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...