why use callbacks

Hi i cant wrap my head around why you would use callbacks

how is

typedef void(*test_callback) (void);

test_callback func1()
{
	Serial.println("func1");
}

void func2()
{
	Serial.println("func2 start");
	
	func1();
	
	Serial.println("func2 end");
}


//in the program call func2;
func2();

any different from

void func1()
{
	Serial.println("func1");
}

void func2()
{
	Serial.println("func2 start");
	
	func1();
	
	Serial.println("func2 end");
}


//in the program call func2;
func2();

There is no difference when all code written by you, but there is big difference when you are using library written by somebody else, and some events need to be tripped by some conditions, in this case event from library code may call callback function in your code.

The first version produces more warnings, it only has the name callback in them, it does not use any.

The function that should return a function pointer does not return any value.

serge,
why would you not just use the public interface of a class to run said code

it does not use any.

any what?

joeblogs:
serge,
why would you not just use the public interface of a class to run said code
any what?

You do not need to have classes and interfaces in order to call callback-functions, callbacks are not only for OOP.

sorry i dont want to drag this out, but if not using classes. why wouldnt you include the header file and then call the function you want to run.

could anyone give me tell me in what situation you would use a callback because it was the best option

When you want to defer a function that is triggered by a subsequent event. That trigger can be a timer or an interrupt, for example.

Callbacks are VERY common and used a lot in async activity.

joeblogs:
sorry i dont want to drag this out, but if not using classes. why wouldnt you include the header file and then call the function you want to run.

could anyone give me tell me in what situation you would use a callback because it was the best option

I said - "not only for OOP" , I did not say "not using classes".
If you are planning to use interfaces - you have to make your own class, inherited from existing one.
If you are planning to use callbacks - you do not need to inherit, all you need is just to declare your own function and set it as a callback.

The best option to use callbacks is definitelly when you are using some library code which written on that way to enforce you to use callbacks :slight_smile:

In case if you are writing both, library and main code, I believe there is no better solution if you are writing some lightweight classes (good sample - simple timer) based on idea nobody will inherit from it, but you need to have some custom events.

joeblogs:
Hi i cant wrap my head around why you would use callbacks

The most common use of a callback function i know of with arduino is with attachInterrupt() function. it uses your function when an event occurs outside of your normal program and you get to tell it what you want done.
the blink function is stored inside of attach interrupts as a pointer to your function and is called when the interrupt occurs.

The most common use of a callback function is with attachInterrupt()
const byte ledPin = 13;
const byte interruptPin = 2;
volatile byte state = LOW;

void setup() {
  pinMode(ledPin, OUTPUT);
  pinMode(interruptPin, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(interruptPin), blink, CHANGE);
}

void loop() {
  digitalWrite(ledPin, state);
}

void blink() {
  state = !state;
}

Heres some discussions I had on this forum: https://forum.arduino.cc/index.php?topic=436961.0
and an incredible resource by Nick on function pointers can be found here: Gammon Forum : Electronics : Microprocessors : Function pointers / function callbacks / function variables

got it

so say for example a class function that is of type ‘callback’ gives you the ability to use that function in a handler. even though the class object may not exist at compile time?

ie.

class with callback function

typedef void(*test_callback)(void);

class InputRecorder
{
public:
	
	test_callback test_func()
	{
		int i = 1;
	}
};

function which creates class object

void data_recorder_run()
{
	InputRecorder DataRec;   // <--classs object doesnt exist prior to calling function
	
	while(program_state == OptID::Opt1)
	{
		DataRec.flow_control();
	}
}

and handler

void PIOC_Handler(void)
{
	uint32_t status = INPUT_PIN_PORT->PIO_ISR;
	
	DataRec.test_func();
}

because the class function has been typedef’d as callback now i can use the function in the handler, where as before the class object had to exist at compile time to have access to its functions/data.

joeblogs:
sorry i dont want to drag this out, but if not using classes. why wouldnt you include the header file and then call the function you want to run.

could anyone give me tell me in what situation you would use a callback because it was the best option

OK, but lets say the function you want to run has to call some function from your code. Imagine I wrote a custom class for sequencing led light patterns. But all it does is sequence the patters. You have to actually write the code for the patterns themselves, the class only controls showing those patterns in a certain order. I might do this so that you can use it for multiple different styles of led strips as long as you can write functions to set the colors to what you want.

So when you call the code in the class, you need to give it the code to make the pattern. So you might call the code to add a pattern into the sequence and pass a pointer to the function you wrote in your code that actually tells your particular lights to come on and what color to be. And that would be an example of a callback. You are telling the library code that when it decides to light up that specific pattern to "call back" to your code for the function to light the strips.

so you can pass a function as an argument in a function

callback my_callback()
{
foo++;
}

other_function(num, my_callback() )
{
if(foo > num) {x = y}
}

thanks for the help.

nicks info was pretty informative. the use of unnamed functions and array indexing looks real handy.

as far as debugging goes are there any pitfalls to using callbacks?

joeblogs:
so you can pass a function as an argument in a function

This is an example of passing a function as an argument in a function

/*** 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 BlinkIt(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(LED_BUILTIN, OUTPUT);
  BlinkIt(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

I think it's reasonable to use a callback for an application such as attachInterrupt() but generally I feel they're not very beginner friendly. You have this function that gets called out of nowhere which makes it hard to understand the program flow from reading the code. I know they confused me when I first encountered them in the PubSubClient library. In that case I would prefer to just call the function from my own code according to a return value from a function of the library.

pert:
You have this function that gets called out of nowhere...

I wouldn't say "called out of nowhere" they do need to be passed as arguments, after all.

They really cannot be generalized to a single example.

I used callbacks when I was building a user interface. I let each class build its area of the interface with various input fields and then used callbacks to get the info back to the class while the user was interacting with the gui.

Keith,
did you do this by using interrupts, once the fields were full the isr fired giving you the info, callback got changed to suit next lot of info?

Callbacks are essentially a software equivalent of interrupts.
Very useful for "event driven programming" (and a lot of desktop programming these days is "event driven" - do this on a mouseClick, and this other thing on a keyboard character, and so on. So the concept is very popular.)

The code that invoke the callback is not YOURS; it's off in a library or an operating system somewhere. So you can't just put a call to the actual function there. Also, you want it to be able to be changed; instead of having mouseClick code that has a giant if/else chain or case statement for all the different handling cases for a mouse event (text area, menu heading, sub-menu, radio-button...), you can just update the callback.

That doesn't mean that callbacks are needed every time you see them used, but they ARE very useful.

chhers westfw,
i can set up and use callbacks ok, but havent built a program that needed to use them widely yet, but can see them as being real handy (especially the c++ versions).

still cant see

The code that invoke the callback is not YOURS

might work in a practical example, i thought the callback was invoked by the fact that you had put the callback in the code. but what the callback DOES depends on the function being assigned to the callback.

im moments away from going neck level, could someone maybe write some simple psuedo to demonstrate a real practical embedded example.
. .>
.
.
neck level . .