Function as a parameter in Class object / Function Pointer in Library

Hello,

I need some help with this as i googled everywhere and couldn't find a good answer.

How do you pass a function as a parameter to create a class object? Something like this:

class exampleClass 
{
  void myFunction();

  public:
  timer( void *func())
  {
       myFunction = func();
   }

  void update()
   {
        myFunction();
   }

};

exampleClass obj1(exampleFunction);

void exampleFunction() 
{
    Serial.Println("hello");
}

Your pseudocode makes no sense. You never call update() or myFunction() so what are you expecting to happen?

Look at how some of the libraries do it. Something like a timer library or state-machine library can call an arbitrary function that is handed to it in setup() or loop().

you may be looking for something like this:
by nickgammon
Function pointers / function callbacks / function variables

Example code:

/*** This code could be hidden within a class or library somewhere ***/
typedef void (*voidFuncPtr)(void);// Create a type to point to a funciton.
static voidFuncPtr  _CallBackFuncitonPointer; // Create an instance of the empty function pointer

void onBlick(voidFuncPtr CallBackFuncitonPointer) {
  _CallBackFuncitonPointer = CallBackFuncitonPointer; // assign a function to the empty function pointer
}
void Blink(unsigned long msDelaTime) {
  if (_CallBackFuncitonPointer) {
    static unsigned long _ATimer;
    if ( (unsigned long)(millis() - _ATimer) >= (msDelaTime)) {
      _ATimer = millis();
      _CallBackFuncitonPointer(); // call the function we assigned to the once empty function pointer
    }
  }
}
/***********************************************************************/
// include "MyLibrary.h" for example that contains the above code


void setup() {
  pinMode(13, OUTPUT);
  onBlick(MySpecialBlinkFunction); // Set my function into the above function pointer
}

void loop() {
  Blink(1000); // Call blink function with the  below function within with 1 second interval
}

void MySpecialBlinkFunction (){
   digitalWrite(13, !digitalRead(13));
}

Z

Thanks guys. I read the code and link above, they are mostly talking about function pointer to other functions. I wanted to do it with a Class. I omitted some lines of code from the examples, but somehow this worked… now I wonder why I’m missing here, is there some weakness here?? Thanks.

Background:
This code is based on a timer that turns a LED on and off. I added a counter and some other codes. I then decided to add a function parameter that should run overtime the LED is turned on.

class timer
{
  // Class Member Variables
  // These are initialized at startup
  int Pin;      // the number of pin being controlled
  long OnTime;     // milliseconds of on-time
  long OffTime;    // milliseconds of off-time
  int maxCount;    //number of times it can run
  int counter;     //run this many times before stopping

  typedef void(*someFunction)(void);
 
  // These maintain the current state
  int pinState;
  unsigned long previousMillis;

  
  public:
  timer(int pin, long on, long off, int count, someFunction myFunction)  //which pin to control , how long to turn on, off, how many times.
  {
  Pin = pin;
  pinMode(Pin, OUTPUT);     
    
  OnTime = on;
  OffTime = off;
  maxCount = count;
  
  
  pinState = LOW; 
  previousMillis = 0;
  counter = 0;
  }

  void Update(unsigned long currentMillis, someFunction myFunction)
  {
      if((pinState == HIGH) && (currentMillis - previousMillis >= OnTime))
      {
        pinState = LOW;  // Turn it off
        previousMillis = currentMillis;  // Remember the time
        digitalWrite(Pin, pinState);    // Update the pin
      }
      else if ((pinState == LOW) && (currentMillis - previousMillis >= OffTime) && (counter < maxCount))
      {
        pinState = HIGH;
        previousMillis = currentMillis;
        digitalWrite(Pin, pinState);
        counter = counter + 1;
        myFunction();
      }
  }

  void Reset()
  {
    counter = 0;
  }

  void Change(int pin, long on, long off, int count, someFunction myFunction)
  {
    Pin = pin;
    pinMode(Pin, OUTPUT);     
    OnTime = on;
    OffTime = off;
    maxCount = count;
  }
  
};

void setup() {
  Serial.begin(9600);
  
  //generate a 'TIMER0_COMPA' interrupt whenever the counter value passes 0xAF
  OCR0A = 0xAF;
  TIMSK0 |= _BV(OCIE0A);
  
}

timer led1(LED_BUILTIN, 2000, 5000, 5, customFunction); //creates object

//interrupt is called once a millisecond
SIGNAL(TIMER0_COMPA_vect) 
{
  unsigned long currentMillis = millis();
  led1.Update(currentMillis, customFunction);

} 

void loop() {

//testing the code outside of the loop()...
  delay(60000);
  led1.Reset();   //reset the counter
  delay(60000);
  led1.Change(LED_BUILTIN, 5000,2000,3, customFunction);  //change the parameters of the object

  
}

void customFunction() {
  Serial.println ("custom function executed.");
}

airoscar:
Thanks guys. I read the code and link above, they are mostly talking about function pointer to other functions. I wanted to do it with a Class. I omitted some lines of code from the examples, but somehow this worked… now I wonder why I’m missing here, is there some weakness here?? Thanks.

Background:
This code is based on a timer that turns a LED on and off. I added a counter and some other codes. I then decided to add a function parameter that should run overtime the LED is turned on.

class timer

{
 // Class Member Variables
 // These are initialized at startup
 int Pin;      // the number of pin being controlled
 long OnTime;     // milliseconds of on-time
 long OffTime;    // milliseconds of off-time
 int maxCount;    //number of times it can run
 int counter;     //run this many times before stopping

typedef void(*someFunction)(void);

// These maintain the current state
 int pinState;
 unsigned long previousMillis;

public:
 timer(int pin, long on, long off, int count, someFunction myFunction)  //which pin to control , how long to turn on, off, how many times.
 {
 Pin = pin;
 pinMode(Pin, OUTPUT);    
   
 OnTime = on;
 OffTime = off;
 maxCount = count;
 
 
 pinState = LOW;
 previousMillis = 0;
 counter = 0;
 }

void Update(unsigned long currentMillis, someFunction myFunction)
 {
     if((pinState == HIGH) && (currentMillis - previousMillis >= OnTime))
     {
       pinState = LOW;  // Turn it off
       previousMillis = currentMillis;  // Remember the time
       digitalWrite(Pin, pinState);    // Update the pin
     }
     else if ((pinState == LOW) && (currentMillis - previousMillis >= OffTime) && (counter < maxCount))
     {
       pinState = HIGH;
       previousMillis = currentMillis;
       digitalWrite(Pin, pinState);
       counter = counter + 1;
       myFunction();
     }
 }

void Reset()
 {
   counter = 0;
 }

void Change(int pin, long on, long off, int count, someFunction myFunction)
 {
   Pin = pin;
   pinMode(Pin, OUTPUT);    
   OnTime = on;
   OffTime = off;
   maxCount = count;
 }
 
};

void setup() {
 Serial.begin(9600);
 
 //generate a ‘TIMER0_COMPA’ interrupt whenever the counter value passes 0xAF
 OCR0A = 0xAF;
 TIMSK0 |= _BV(OCIE0A);
 
}

timer led1(LED_BUILTIN, 2000, 5000, 5, customFunction); //creates object

//interrupt is called once a millisecond
SIGNAL(TIMER0_COMPA_vect)
{
 unsigned long currentMillis = millis();
 led1.Update(currentMillis, customFunction);

}

void loop() {

//testing the code outside of the loop()…
 delay(60000);
 led1.Reset();   //reset the counter
 delay(60000);
 led1.Change(LED_BUILTIN, 5000,2000,3, customFunction);  //change the parameters of the object

}

void customFunction() {
 Serial.println (“custom function executed.”);
}

I’m afraid your serial print could cause issues because it is part of the timer.

//interrupt is called once a millisecond
SIGNAL(TIMER0_COMPA_vect)

Also all variables used within the interrupts and needed outside the interrupts must have the volatile keyword included to be up to date with there values when read

 volatile int foo;

I may have missed something but that is what I see first.
z

maybe look up static class functions, where the function itself is not tied to an object and in that function you might be able to create an object

airoscar:
How do you pass a function as a parameter to create a class object?

It is very straightforward, and your code wasn't far off...

you simply pass a function pointer.

Say you have a function that does something:

void myFunction(void)
{
  // do something
}

you pass a pointer to the function to a class member object, here I used the constructor:

class MyClass{
  public:
    MyClass(void(*someFunctionPointer)(void)) {funct = someFunctionPointer;};
    void runFunction(void) {funct();};
  private:
    void(*funct)(void);
};

void myFunction(void);

MyClass someInstance(myFunction); // myFunction (name) resolves to a pointer to the myFunction() function.

void setup() 
{
  Serial.begin(9600);
  someInstance.runFunction();
}

void loop() {}

void myFunction(void)
{
  Serial.print("ran the function");
}

of course the function pointer you pass must match the function signature in the class member function

Thanks guys!

BulldogLowell that is an excellent example, it was exactly what I was looking for. Thanks a bunch guys.

BulldogLowell:
It is very straightforward, and your code wasn't far off...

you simply pass a function pointer.

Say you have a function that does something:

void myFunction(void)

{
  // do something
}




you pass a pointer to the function to a class member object, here I used the constructor:



class MyClass{
  public:
    MyClass(void(*someFunctionPointer)(void)) {funct = someFunctionPointer;};
    void runFunction(void) {funct();};
  private:
    void(*funct)(void);
};

void myFunction(void);

MyClass someInstance(myFunction); // myFunction (name) resolves to a pointer to the myFunction() function.

void setup()
{
  Serial.begin(9600);
  someInstance.runFunction();
}

void loop() {}

void myFunction(void)
{
  Serial.print("ran the function");
}





of course the function pointer you pass must match the function signature in the class member function

here is the Class for executing two functions at a timed interval for specific number of cycles btw.

Based on tutorial found here: Overview | Multi-tasking the Arduino - Part 2 | Adafruit Learning System

and with the help from above posts regarding passing function to class members.

class functionTimer
{
  int Pin;      // the number of pin being controlled
  long OnTime;     // milliseconds of on-time
  long OffTime;    // milliseconds of off-time
  int maxCount;    //number of times it can run
  int counter;
 
  int onoffState;
  unsigned long previousMillis;

  public:
  functionTimer(long on, void(*onFunctionPointer)(void) , long off, void(*offFunctionPointer)(void), int count)  //which pin to control , how long to turn on, off, how many times.
  {   
    
  OnTime = on;
  OffTime = off;
  maxCount = count;
  onoffState = 0; 
  previousMillis = 0;
  counter = 0;
  Function1 = onFunctionPointer;
  Function2 = offFunctionPointer;
  
  };

  void runFunction(unsigned long currentMillis)
  {
      if((onoffState == 1) && (currentMillis - previousMillis >= OnTime))
      {
        onoffState = 0;  // Turn it off
        previousMillis = currentMillis;  // Remember the time
        Function2();
        
      }
      else if ((onoffState == 0) && (currentMillis - previousMillis >= OffTime) && (counter < maxCount))
      {
        onoffState = 1;
        previousMillis = currentMillis;
        counter = counter + 1;
        Function1();
      }
      
  };

  void Reset()
  {
    counter = 0;
  };

  void Update(long on, void(*onFunctionPointer)(void) , long off, void(*offFunctionPointer)(void), int count)
  {
     
    OnTime = on;
    OffTime = off;
    maxCount = count;
  };

  private:
  void(*Function1)(void);
  void(*Function2)(void);
  
};

void setup() {
  
  //generate a 'TIMER0_COMPA' interrupt whenever the counter value passes 0xAF
  OCR0A = 0xAF;
  TIMSK0 |= _BV(OCIE0A);

  pinMode(LED_BUILTIN, OUTPUT);
}

functionTimer led1(1000, customFunction, 3000, customFunction2, 5); //creates object

//interrupt is called once a millisecond
SIGNAL(TIMER0_COMPA_vect) 
{
  unsigned long currentMillis = millis();
  led1.runFunction(currentMillis);

} 

void loop() {

//for testing the code//
  delay(60000);
  led1.Reset();   //reset the counter
  led1.Update(5000, customFunction, 1000, customFunction2, 3);  //change the parameters of the object
  
}

//for testing the code
void customFunction() {
  digitalWrite(LED_BUILTIN, HIGH);
}

//for testing the code
void customFunction2() {
  digitalWrite(LED_BUILTIN, LOW);
}

Hi guys, sorry more question…

I’m trying to turn above code into a Library… and yet again I’m having trouble with this function pointer stuff…

I’ve built the header as such:

#ifndef functionTimer_h
#define functionTimer_h

#include "Arduino.h"


class functionTimer
{

  public:
    functionTimer(long on, void(*onFunctionPointer)(void) , long off, void(*offFunctionPointer)(void), int count);  //which pin to control , how long to turn on, off, how many times.

    void runFunction(unsigned long currentMillis);
  

  void Reset();

  void Update(long on, void(*onFunctionPointer)(void) , long off, void(*offFunctionPointer)(void), int count);

  private:
  void (*Function1(void));
  void (*Function2(void));
  int _onoffState;
  unsigned long _previousMillis;
  int _counter;
  int _maxCount;
  long _OnTime;
  long _OffTime;
    
};


#endif

and the main codes:

#include "Arduino.h"
#include "functionTimer.h"

functionTimer::functionTimer(long on, void(*onFunctionPointer)(void) , long off, void(*offFunctionPointer)(void), int count)
{
  _OnTime = on;
  _OffTime = off;
  _maxCount = count;
  _onoffState = 0;
  _previousMillis = 0;
  _counter = 0;
  Function1 = onFunctionPointer;
  Function2 = offFunctionPointer;
  
  };

void functionTimer::runFunction(unsigned long currentMillis)
  {
      currentMillis = currentMillis;
      if((_onoffState == 1) && (currentMillis - _previousMillis >= _OnTime))
      {
        _onoffState = 0;
        _previousMillis = currentMillis;
        Function1();
        
      }
      else if ((_onoffState == 0) && (currentMillis - _previousMillis >= _OffTime) && (_counter < _maxCount))
      {
        _onoffState = 1;
        _previousMillis = currentMillis;
        _counter = _counter + 1;
        Function2();
      }
      
  };

void functionTimer::Reset()
  {
    _counter = 0;
  };

void functionTimer::Update(long on, void(*onFunctionPointer)(void) , long off, void(*offFunctionPointer)(void), int count)
  {
     
    _OnTime = on;
    _OffTime = off;
    _maxCount = count;
  };

And i set up a sketch to test the library:

#include <functionTimer.h>
void setup() {
  
  //generate a 'TIMER0_COMPA' interrupt whenever the counter value passes 0xAF
  OCR0A = 0xAF;
  TIMSK0 |= _BV(OCIE0A);

  pinMode(LED_BUILTIN, OUTPUT);
}

functionTimer led1(1000, customFunction, 3000, customFunction2, 5); //creates object

//interrupt is called once a millisecond
SIGNAL(TIMER0_COMPA_vect) 
{
  unsigned long currentMillis = millis();
  led1.runFunction(currentMillis);

} 

void loop() {

//for testing the code//
  delay(60000);
  led1.Reset();   //reset the counter
  led1.Update(5000, customFunction, 1000, customFunction2, 3);  //change the parameters of the object
  
}

//for testing the code
void customFunction() {
  digitalWrite(LED_BUILTIN, HIGH);
}

//for testing the code
void customFunction2() {
  digitalWrite(LED_BUILTIN, LOW);
}

But the compiler gives this error:

functionTimer.cpp:14:15: error: lvalue required as left operand of assignment
   Function1() = onFunctionPointer();
               ^

What am I missing here?

you have a syntax issue here at least:

 private:
  void (*Function1(void));
  void (*Function2(void));

should look more like this:

 private:
  void (*Function1)(void);
  void (*Function2)(void);

Thanks BulldogLowell! You solved it again!