Callback
A callback is a user provided function that a user may pass to an API. The callback allows the API to execute the user’s code in its own context.
This is the technical reference for callbacks. You should read the Callbacks section of the Platform Overview first for deeper insight into their use.
Calling callbacks
Callbacks overload the function call operator, so you can call a Callback like you would a normal function:
void run_timer_event(Callback<void(float)> on_timer) {
on_timer(1.0f);
}
The only thing to watch out for is that the Callback type has a null Callback, just like a null function pointer. Uninitialized callbacks are null and assert if you call them. If you want a call to always succeed, you need to check if it is null first.
void run_timer_event(Callback<void(float)> on_timer) {
if (on_timer) {
on_timer(1.0f);
}
}
The Callback class is what’s known in C++ as a “Concrete Type”. That is, the Callback class is lightweight enough to be passed around like an int, pointer or other primitive type.
Callback class reference
Public Member Functions | |
Callback (R(*func)(A0, A1, A2, A3, A4)=0) | |
Create a Callback with a static function. More... | |
Callback (const Callback< R(A0, A1, A2, A3, A4)> &func) | |
Attach a Callback. More... | |
template<typename T , typename U > | |
Callback (U *obj, R(T::*method)(A0, A1, A2, A3, A4)) | |
Create a Callback with a member function. More... | |
template<typename T , typename U > | |
Callback (const U *obj, R(T::*method)(A0, A1, A2, A3, A4) const) | |
Create a Callback with a member function. More... | |
template<typename T , typename U > | |
Callback (volatile U *obj, R(T::*method)(A0, A1, A2, A3, A4) volatile) | |
Create a Callback with a member function. More... | |
template<typename T , typename U > | |
Callback (const volatile U *obj, R(T::*method)(A0, A1, A2, A3, A4) const volatile) | |
Create a Callback with a member function. More... | |
template<typename T , typename U > | |
Callback (R(*func)(T *, A0, A1, A2, A3, A4), U *arg) | |
Create a Callback with a static function and bound pointer. More... | |
template<typename T , typename U > | |
Callback (R(*func)(const T *, A0, A1, A2, A3, A4), const U *arg) | |
Create a Callback with a static function and bound pointer. More... | |
template<typename T , typename U > | |
Callback (R(*func)(volatile T *, A0, A1, A2, A3, A4), volatile U *arg) | |
Create a Callback with a static function and bound pointer. More... | |
template<typename T , typename U > | |
Callback (R(*func)(const volatile T *, A0, A1, A2, A3, A4), const volatile U *arg) | |
Create a Callback with a static function and bound pointer. More... | |
template<typename F > | |
Callback (F f,) | |
Create a Callback with a function object. More... | |
template<typename F > | |
Callback (const F f,) | |
Create a Callback with a function object. More... | |
template<typename F > | |
Callback (volatile F f,) | |
Create a Callback with a function object. More... | |
template<typename F > | |
Callback (const volatile F f,) | |
Create a Callback with a function object. More... | |
template<typename T , typename U > | |
Callback (U *obj, R(*func)(T *, A0, A1, A2, A3, A4)) | |
Create a Callback with a static function and bound pointer. More... | |
template<typename T , typename U > | |
Callback (const U *obj, R(*func)(const T *, A0, A1, A2, A3, A4)) | |
Create a Callback with a static function and bound pointer. More... | |
template<typename T , typename U > | |
Callback (volatile U *obj, R(*func)(volatile T *, A0, A1, A2, A3, A4)) | |
Create a Callback with a static function and bound pointer. More... | |
template<typename T , typename U > | |
Callback (const volatile U *obj, R(*func)(const volatile T *, A0, A1, A2, A3, A4)) | |
Create a Callback with a static function and bound pointer. More... | |
~Callback () | |
Destroy a callback. More... | |
void | attach (R(*func)(A0, A1, A2, A3, A4)) |
Attach a static function. More... | |
void | attach (const Callback< R(A0, A1, A2, A3, A4)> &func) |
Attach a Callback. More... | |
template<typename T , typename U > | |
void | attach (U *obj, R(T::*method)(A0, A1, A2, A3, A4)) |
Attach a member function. More... | |
template<typename T , typename U > | |
void | attach (const U *obj, R(T::*method)(A0, A1, A2, A3, A4) const) |
Attach a member function. More... | |
template<typename T , typename U > | |
void | attach (volatile U *obj, R(T::*method)(A0, A1, A2, A3, A4) volatile) |
Attach a member function. More... | |
template<typename T , typename U > | |
void | attach (const volatile U *obj, R(T::*method)(A0, A1, A2, A3, A4) const volatile) |
Attach a member function. More... | |
template<typename T , typename U > | |
void | attach (R(*func)(T *, A0, A1, A2, A3, A4), U *arg) |
Attach a static function with a bound pointer. More... | |
template<typename T , typename U > | |
void | attach (R(*func)(const T *, A0, A1, A2, A3, A4), const U *arg) |
Attach a static function with a bound pointer. More... | |
template<typename T , typename U > | |
void | attach (R(*func)(volatile T *, A0, A1, A2, A3, A4), volatile U *arg) |
Attach a static function with a bound pointer. More... | |
template<typename T , typename U > | |
void | attach (R(*func)(const volatile T *, A0, A1, A2, A3, A4), const volatile U *arg) |
Attach a static function with a bound pointer. More... | |
template<typename F > | |
void | attach (F f,) |
Attach a function object. More... | |
template<typename F > | |
void | attach (const F f,) |
Attach a function object. More... | |
template<typename F > | |
void | attach (volatile F f,) |
Attach a function object. More... | |
template<typename F > | |
void | attach (const volatile F f,) |
Attach a function object. More... | |
template<typename T , typename U > | |
void | attach (U *obj, R(*func)(T *, A0, A1, A2, A3, A4)) |
Attach a static function with a bound pointer. More... | |
template<typename T , typename U > | |
void | attach (const U *obj, R(*func)(const T *, A0, A1, A2, A3, A4)) |
Attach a static function with a bound pointer. More... | |
template<typename T , typename U > | |
void | attach (volatile U *obj, R(*func)(volatile T *, A0, A1, A2, A3, A4)) |
Attach a static function with a bound pointer. More... | |
template<typename T , typename U > | |
void | attach (const volatile U *obj, R(*func)(const volatile T *, A0, A1, A2, A3, A4)) |
Attach a static function with a bound pointer. More... | |
Callback & | operator= (const Callback &that) |
Assign a callback. More... | |
R | call (A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) const |
Call the attached function. More... | |
R | operator() (A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) const |
Call the attached function. More... | |
operator bool () const | |
Test if function has been attached. More... |
Static Public Member Functions | |
static R | thunk (void *func, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) |
Static thunk for passing as C-style function. More... |
Friends | |
bool | operator== (const Callback &l, const Callback &r) |
Test for equality. More... | |
bool | operator!= (const Callback &l, const Callback &r) |
Test for inequality. More... |
Serial passthrough example with callbacks
#include "mbed.h"
RawSerial pc(USBTX, USBRX);
RawSerial dev(D1, D0);
DigitalOut led1(LED1);
DigitalOut led4(LED4);
void dev_recv()
{
led1 = !led1;
while(dev.readable()) {
pc.putc(dev.getc());
}
}
void pc_recv()
{
led4 = !led4;
while(pc.readable()) {
dev.putc(pc.getc());
}
}
int main()
{
pc.baud(9600);
dev.baud(9600);
pc.attach(&pc_recv, Serial::RxIrq);
dev.attach(&dev_recv, Serial::RxIrq);
while(1) {
sleep();
}
}
Thread example with callbacks
The Callback API provides a convenient way to pass arguments to spawned threads. This example uses a C function pointer in the Callback.
#include "mbed.h"
Thread thread;
DigitalOut led1(LED1);
volatile bool running = true;
// Blink function toggles the led in a long running loop
void blink(DigitalOut *led) {
while (running) {
*led = !*led;
wait(1);
}
}
// Spawns a thread to run blink for 5 seconds
int main() {
thread.start(callback(blink, &led1));
wait(5);
running = false;
thread.join();
}
Sonar example
Here is an example that uses everything discussed in the introduction to callbacks document in the form of a minimal Sonar class. This example uses a C++ class and method in the Callback.
#include "mbed.h"
/**
* Sonar class for the HC-SR04
*/
class Sonar {
DigitalOut trigger;
InterruptIn echo; // calls a callback when a pin changes
Timer timer;
Timeout timeout; // calls a callback once when a timeout expires
Ticker ticker; // calls a callback repeatedly with a timeout
int32_t begin;
int32_t end;
float distance;
public:
/**
* Sonar constructor
* Creates a sonar object on a set of provided pins
* @param trigger_pin Pin used to trigger reads from the sonar device
* @param echo_pin Pin used to receive the sonar's distance measurement
*/
Sonar(PinName trigger_pin, PinName echo_pin) : trigger(trigger_pin), echo(echo_pin) {
trigger = 0;
distance = -1;
echo.rise(callback(this, &Sonar::echo_in)); // Attach handler to the rising interruptIn edge
echo.fall(callback(this, &Sonar::echo_fall)); // Attach handler to the falling interruptIn edge
}
/**
* Start the background task to trigger sonar reads every 100ms
*/
void start(void) {
ticker.attach(callback(this, &Sonar::background_read), 0.01f);
}
/**
* Stop the background task that triggers sonar reads
*/
void stop(void) {
ticker.detach();
}
/**
* Interrupt pin rising edge interrupt handler. Reset and start timer
*/
void echo_in(void) {
timer.reset();
timer.start();
begin = timer.read_us();
}
/**
* Interrupt pin falling edge interrupt handler. Read and disengage timer.
* Calculate raw echo pulse length
*/
void echo_fall(void) {
end = timer.read_us();
timer.stop();
distance = end - begin;
}
/**
* Wrapper function to set the trigger pin low. Callbacks cannot take in both object and argument pointers.
* See use of this function in background_read().
*/
void trigger_toggle(void) {
trigger = 0;
}
/**
* Background callback task attached to the periodic ticker that kicks off sonar reads
*/
void background_read(void) {
trigger = 1;
timeout.attach(callback(this, &Sonar::trigger_toggle), 10.0e-6);
}
/**
* Public read function that returns the scaled distance result in cm
*/
float read(void) {
return distance / 58.0f;
}
};
int main() {
// Create sonar object on pins D5 and D6
Sonar sonar(D5, D6);
// Begin background thread sonar acquires
sonar.start();
while(1) {
wait(0.1f);
// Periodically print results from sonar object
printf("%f\r\n", sonar.read());
}
}