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()
{ }
};