I try to implement a task which is called within a C++Class and it needs a callback-function. As I'm pretty new to C++ and although I have a rough understanding for pointers this is something I couldn't figure out yet:
I'm using the TaskScheduler library to setup everything needed in class I want to call the following function. The normal examples for arduino don't use classes and I'm struggling to get it work in my refactored code.
void Weather::setup(std::shared_ptr<Scheduler> s ,int id, String appid, uint32_t interval)
{
...
weatherTask(interval, TASK_FOREVER, &Weather::updateWeatherCallback, *scheduler, true);
}
the updateWeatherCallback-function is implemented in this class too:
void Weather::updateWeatherCallback() {...}
Asides using the Code above I tried some lambda Variants suggested here on Stackoverflow and simply the following:
weatherTask(interval,TASK_FOREVER, [this](){this->updateWeatherCallback;},*scheduler,true);
But I figured that my understanding of these answers on Stackoverflow is not good -its more trial and error- which makes searching for "the right answers" difficult
Some details from the 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);
...
weatherTask wants a function pointer and not a pointer to a member. A possible way to solve this problem is to create a helper struct and bind the function to a 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;
When creating the weatherTask use the following to bind the member function to your callback:
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);
The solution was presented as an anwser to this question. Since I cannot comment I decided to provide this as an answer.
Alternatively you can make use of a trampoline like function. Therefore you would be required to store an global pointer to your Weather
object.
Weather global_ptr;
Then you would be able to create a weatherTask
using a lambda function.
weatherTask(interval, TASK_FOREVER, [](){global_ptr->updateWeatherCallback();}, *scheduler, true);