Skip to main content
7 of 7
replaced http://arduino.stackexchange.com/ with https://arduino.stackexchange.com/

pass class internal function as callback

I am trying to pass a class internal function as a callback function within the class. The error behavior is similar to this problem. Whatsoever, I was unable to construct working code based on that question's answer.

I try to pass over a callback function from within the class,in order to create a finite state machine, inspired by the examples I found on adafruit regarding multithreading. The idea is, that each state can call his successor. The class itself then represents the state machine and I just will call its update function.

While the following code does not resemble this utility, it resembles the problem in a minimal example (based on this larger codepiece):

class MyClass
{
  const byte theAnswer = 42;
  void (*myCallback)();

  void setCallback(void (*callback)())
  {
    myCallback = callback;
  }
  
  public:
  
  void print_info()
  {
    Serial.println(theAnswer);
  }

  void call()
  {
    myCallback();
  }
  
   MyClass()
  {
    setCallback(&MyClass::print_info);
  }
};


MyClass AClassOfItsOwn();

void setup() 
{
  Serial.begin(9600);
  while (! Serial); // Wait until Serial is ready
}

void loop() 
{
  AClassOfItsOwn.call();
  return;
}

I get the following error code returned:

...testscript.ino: In constructor 'MyClass::MyClass()':

testscript:25: error: no matching function for call to 'MyClass::setCallback(void (MyClass::*)())'

     setCallback(&MyClass::print_info);

                                     ^

...\testscript.ino:25:41: note: candidate is:

...\testscript.ino:6:12: note: void MyClass::setCallback(void (*)())

   void setCallback(void (*callback)())

        ^

...\testscript.ino:6:12: note: no known conversion for argument 1 from 'void (MyClass::)()' to 'void ()()'

...\testscript.ino: In function 'void loop()':

testscript:40: error: request for member 'call' in 'AClassOfItsOwn', which is of non-class type 'MyClass()'

   AClassOfItsOwn.call();

                  ^

exit status 1 no matching function for call to 'MyClass::setCallback(void (MyClass::*)())'


fun times with polymorphism

This is code we discussed during looking for a solution. I leave it here for future reference.

I tried creating an instance of this wrapper within the actual class to hold the callback, but that did not work either.

class CallbackWrapper
{
  void (*myCallback)();
  public:
  
  void call()
  {
    myCallback();
  }

  void setCallback(void (*callback)())
  {
    myCallback = callback;
  }
};

class MyClass : public CallbackWrapper
{
  const byte theAnswer = 42;
  public:
  
  void print_info()
  {
    Serial.println(theAnswer);
  }
  
   MyClass()
  {
    CallbackWrapper::setCallback(&MyClass::print_info);
  }
};

trying to store the callback function in a wrapping class (also not working, '((MyClass*)this)->MyClass::CBW' does not have class type)

class CallbackWrapper
{
  void (*myCallback)();
  public:
  
  void call()
  { myCallback(); }

  void setCallback(void (*callback)())
  { myCallback = callback; }
};

class MyClass 
{
  const byte theAnswer = 42;
  CallbackWrapper CBW();
  public:
  void print_info() { Serial.println(theAnswer); }
  void call() { CBW.call(); }
  MyClass()
  { CBW.setCallback(&MyClass::print_info); }
};

An update on why I want to change the callback function during runtime. Here I try to randomly change the callback function:

class MyClass 
{
  CallbackWrapper CBW();
  public:
  void do_this() { Serial.println("doing this"); }
  void do_that() { Serial.println("doing that"); }
  void call() 
  { 
    CBW.call();
    if (rand() > 0.5)
    {
      CBW.setCallback(&MyClass::do_this)
    }
    else
    {
      CBW.setCallback(&MyClass::do_that)
    }
  }
   MyClass()
  {  }
};

For discussion with Michail

class CallbackWrapper
{
  public:
  void (*myCallback)();
  void call()
  { myCallback(); }

  virtual void setCallback(void (*callback)())
  {  }
};

class MyClass : public CallbackWrapper
{
  public:
  void setCallback(void (*callback)())
    { myCallback = callback; }
  void do_this() { Serial.println("doing this"); }
  void do_that() { Serial.println("doing that"); }
  void call() 
  { 
    CallbackWrapper::call();
    if (rand() > 0.5)
    { setCallback(&MyClass::do_this); }
    else
    { setCallback(&MyClass::do_that); }
  }
   MyClass()
  {  }
};
Faultier
  • 143
  • 1
  • 7