Discuss here different C compiler set ups, and compiling executables for the ESP8266
User avatar
By mlefevre
#77802 I'm working on a project using the Ticker library to perform periodic callbacks. I got it working using C but now I'm trying to get a C++ implementation working. I gave up C++ for Python 8 or 9 years ago and am just now re-learning C++. The concepts are still fresh but the syntax is slow to return.

I have an implementation similar to this example from Arduino/libraries/Ticker/examples/TickerFunctional/TickerFunctional.ino:
Code: Select allclass ExampleClass {
  public:
    ExampleClass(int pin, int duration) : _pin(pin), _duration(duration) {
      pinMode(_pin, OUTPUT);
      _myTicker.attach_ms(_duration, std::bind(&ExampleClass::classBlink, this));
    }
    ~ExampleClass() {};

    int _pin, _duration;
    Ticker _myTicker;

    void classBlink() {
      digitalWrite(_pin, !digitalRead(_pin));
    }
};

In this example std::Bind is used to pass a this pointer along with the function reference.
My class looks like this:
Code: Select alltypedef void (*CallbackFn)();
typedef struct
{
  bool           active;        // Is this timeout active?
  bool           repeat;        // Restart this timeout when it expires?
  unsigned int   duration;      // The duration (seconds) for the timeout
  unsigned int   timeoutTime;   // The future time when the timeout occurs
  CallbackFn     callbackFn;    // The function to call if/when the timeout expires
} TimeoutInstance;

class UTimer
{
  public:
    UTimer(Log &info, Log &error);
    ~UTimer() {};
    int setTimeout(unsigned int duration, CallbackFn callbackFn, bool repeat);
    void cancelTimeout(int index);

  private:
    Ticker            timeoutTimer;
    unsigned int      elapsedTime = 0;
    TimeoutInstance   timeouts[NUM_TIMEOUTS];
    Log               &info;
    Log               &error;

    void timeoutMonitor();
};


My constructor looks like this in UTimer.cpp:
Code: Select all#include <UTimer.h>

UTimer::UTimer(Log &info, Log &error) : info(info), error(error)
{
  timeoutTimer.attach_ms(TIMER_TICK_100MS, std::bind(&UTimer::timeoutMonitor, this));
  for (int i = 0; i < NUM_TIMEOUTS; i++) this->timeouts[i].active = false;
}

That attach_ms call fails to compile with the following message:
Code: Select allC:\Users\marc\Documents\PlatformIO\lib\utimer\src\UTimer.cpp: In constructor 'UTimer::UTimer(Log&, Log&)':
C:\Users\marc\Documents\PlatformIO\lib\utimer\src\UTimer.cpp:6:73: error: no matching function for call to 'Ticker::attach_ms(int, void (UTimer::*)(), UTimer* const)'
timeoutTimer.attach_ms(TIMER_TICK_100MS, &UTimer::timeoutMonitor, this);

^
C:\Users\marc\Documents\PlatformIO\lib\utimer\src\UTimer.cpp:6:73: note: candidates are:
In file included from C:\Users\marc\Documents\PlatformIO\lib\utimer\src/UTimer.h:4:0,
from C:\Users\marc\Documents\PlatformIO\lib\utimer\src\UTimer.cpp:1:
C:\Users\marc\.platformio\packages\framework-arduinoespressif8266\libraries\Ticker/Ticker.h:46:7: note: void Ticker::attach_ms(uint32_t, Ticker::callback_t)
void attach_ms(uint32_t milliseconds, callback_t callback)
^
C:\Users\marc\.platformio\packages\framework-arduinoespressif8266\libraries\Ticker/Ticker.h:46:7: note:   candidate expects 2 arguments, 3 provided
C:\Users\marc\.platformio\packages\framework-arduinoespressif8266\libraries\Ticker/Ticker.h:63:7: note: template<class TArg> void Ticker::attach_ms(uint32_t, void (*)(TArg), TArg)
void attach_ms(uint32_t milliseconds, void (*callback)(TArg), TArg arg)
^
C:\Users\marc\.platformio\packages\framework-arduinoespressif8266\libraries\Ticker/Ticker.h:63:7: note:   template argument deduction/substitution failed:
C:\Users\marc\Documents\PlatformIO\lib\utimer\src\UTimer.cpp:6:73: note:   mismatched types 'void (*)(TArg)' and 'void (UTimer::*)()'
timeoutTimer.attach_ms(TIMER_TICK_100MS, &UTimer::timeoutMonitor, this);
^

I've scoured the forums for help on passing member function references to other classes and most seem to suggest std::bind. Can anyone see what I'm doing wrong?
User avatar
By jcmvbkbc
#77869
mlefevre wrote:My constructor looks like this in UTimer.cpp:
Code: Select all#include <UTimer.h>

UTimer::UTimer(Log &info, Log &error) : info(info), error(error)
{
  timeoutTimer.attach_ms(TIMER_TICK_100MS, std::bind(&UTimer::timeoutMonitor, this));
  for (int i = 0; i < NUM_TIMEOUTS; i++) this->timeouts[i].active = false;
}

That attach_ms call fails to compile with the following message:
Code: Select allC:\Users\marc\Documents\PlatformIO\lib\utimer\src\UTimer.cpp: In constructor 'UTimer::UTimer(Log&, Log&)':
C:\Users\marc\Documents\PlatformIO\lib\utimer\src\UTimer.cpp:6:73: error: no matching function for call to 'Ticker::attach_ms(int, void (UTimer::*)(), UTimer* const)'
timeoutTimer.attach_ms(TIMER_TICK_100MS, &UTimer::timeoutMonitor, this);

...
Can anyone see what I'm doing wrong?

The code definitely does not match the error message that you quote.