How to store a callback inside a class?

Hello. I'm writing a scheduler for a project using an ESP8266. I want to create a class called Task, and you can create a new Task like so:

void callback() {
  Serial.println("callback called");
}
int time = 60000; // run callback in 60 seconds
Task myTask(time, callback);

My plan is to then create a function that checks all tasks to see which ones are completed, and run the callback from those.

I ran into some issues trying to pass the callback() function into the class and store it as a variable there. I'm new to C++, but I figured I might be able to store it as a pointer to the function, but I just couldn't get that working.

Does anybody know of a good way to pass and store the callback in the Task class?

Post complete code of what you have tried.

You can define a custom data type that's a pointer to a function with that signature. It will make things a little simpler:

using CallbackType = void (*)();

@tsel1209 It would have been easier if you had provided a skeleton sketch.

here I have a class with an optional callback which gets called when new data is available

https://werner.rothschopf.net/microcontroller/202201_a02yyuw_ultrasonic_sensor_en.htm

Here is my final working code, thanks noiasca:

class Task {
  public:
    void (*callback)();
    int time;
    Task(int x, void (*y)()) {
      time = x;
      callback = y;
    }
};

Using the code above, I'm trying to store many Tasks in a single array, to cycle through them and check if they're completed. I can get them into an array by using the code below, but whenever I try to use sizeof() it returns 4, and whenever I try to use sizeof(arr)/sizeof(arr[0]) that just returns 0.

Task one(3000, function);
Task two(6000, function);
Task three(4000, function);
Task z[] = { one, two, three };
checkTasks(z);

void checkTasks(Task tasks[]) {
  Serial.println(sizeof(tasks));       // always returns 4, regardless of actual length of array
}

That makes copies of one, two, and three in the array. Use an array of pointers instead:

Task *z[] = { &one, &two, &three };

Or, even better, create the array directly:

Task z[] {
  {3000, function},
  {6000, function},
  {4000, function}
};

4 is the number of bytes for a pointer which is really what you are asking for.

unfortunately when you pass an array to a function there is something known as array to pointer decay that happens and you loose the size of the array.

so one way to deal with it is to pass the size alongside the (decayed) array

Task one(3000, function);
Task two(6000, function);
Task three(4000, function);
Task* z[] = {&one, &two, &three };
const size_t zCount = sizeof z / sizeof *z;

checkTasks(z, zCount);

void checkTasks(Task *tasks, zCount) {
  for (size_t i=0; i< zCount; i++) {
    tasks[i]->doThis();
  }
}

depending on which arduino you run, you can use containers that do not have the array legacy constraints

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.