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.
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
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;
}
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;
}
};
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:
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));
}
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.
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 . .
joeblogs:
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?
Nope, no interrupts, my gui would just call a function that my instrument class "registered" with it. westfw explained it well.