-->
Page 1 of 3

Adding ticker callback function error

PostPosted: Tue May 10, 2016 1:37 pm
by frischevollmilch
Hello,
I am working on a project and want to attack a callback function to a ticker. I am using the ESP8266 Ticker library. In the following code snippet I pasted the relevant parts of the Ticker library just to reproduce the error. You would get the same error if you remove the Ticker class and include the Ticker.h.

Code: Select allclass Ticker
{
  public:
    typedef void (*callback_t)(void);
    void attach(float seconds, callback_t callback);
};

class Effect
{
  public:
    Effect()
    {
      ticker.attach(10, tick);
    }
    Ticker ticker;
    typedef void (*callback_t)(void);
    callback_t tick();
};

void setup() {}

void loop() {}


I get the following error when compiling:

Code: Select all[...]\sketch_may10b.ino: In constructor 'Effect::Effect()':

sketch_may10b:13: error: no matching function for call to 'Ticker::attach(int, <unresolved overloaded function type>)'

       ticker.attach(10, tick);

                             ^

[...]\sketch_may10b.ino:13:29: note: candidate is:

[...]\sketch_may10b.ino:5:10: note: void Ticker::attach(float, Ticker::callback_t)

     void attach(float seconds, callback_t callback);

          ^

[...]\sketch_may10b.ino:5:10: note:   no known conversion for argument 2 from '<unresolved overloaded function type>' to 'Ticker::callback_t {aka void (*)()}'

exit status 1
no matching function for call to 'Ticker::attach(int, <unresolved overloaded function type>)'


I think this is weird because I pass tick of type callback_t to the attack method so it should match, right? I am clueless as to what is going on here and would be very happy if you could lead me in the right direction here.

The weird thing to me is: When I do this whole thing outside of classes I can just declare tick() of type void and the attack method takes it without a problem. I don't understand the difference in this case between doing the same thing in and outside of a class.

Thanks a ton!

Re: Adding ticker callback function error

PostPosted: Tue May 10, 2016 2:13 pm
by martinayotte
In C++, the fact that you have a Class method as a callback means that it should receive a "this" pointer, but you don't have one so it doesn't match the signature prototype, unless you make that method "static". Also, you are not properly define your method since you specified that your method is returning a callback instead of a void.

Here is your code modified to be able to compile :

Code: Select alltypedef void (*callback_t)(void);

class Ticker
{
  public:
    void attach(float seconds, callback_t callback);
};

class Effect
{
  public:
    Ticker ticker;
    static void tick() {
       // do something here ...
    };
    Effect()
    {
      ticker.attach(10, tick);
    }
};

Re: Adding ticker callback function error

PostPosted: Tue May 10, 2016 2:28 pm
by frischevollmilch
That way it totally makes sense. Thank you very much!

Re: Adding ticker callback function error

PostPosted: Tue May 10, 2016 4:21 pm
by frischevollmilch
I ran into another problem. Again, I can't change the Ticker class as it's the one that comes with the ESP8266 libraries. My project has an LED matrix which will be able to display light effects. I have this Effect class that should be kind of a "template" (not the term you'd use in C++ I think) for all the effects the matrix should display. So every effect derives from the Effect class. So my code looks like this now:

Code: Select allclass Ticker
{
  public:
    typedef void (*callback_t)(void);
    void attach(float seconds, callback_t callback);
};

class Effect
{
  public:
    Ticker ticker;
    static void tick() {
       // do nothing. function will be defined in derived class...
    };
    Effect()
    {
      ticker.attach(10, tick);
    }
};

class BlinkEffect : public Effect
{
  public:
    static void tick() {
      // do something else here
    }
};


Of course this does not override the Effect::tick() method. I would have to make it virtual instead but it's already static and virtual static is not possible. Is there any way to work around this or will I have to overthink the whole thing again from scratch?