Callback
回调是用户提供的功能,用户可以将其传递给 API。回调允许 API 在其自己的上下文中执行用户代码。
这是回调的技术参考。您应首先阅读 “平台概述” 的 “回调” 部分,以深入了解其用途。
Callback 类参考
mbed::Callback< R(A0, A1, A2, A3, A4)> 类模板参考
公共成员函数 | |
Callback (R(*func)(A0, A1, A2, A3, A4)=0) | |
Callback (const Callback< R(A0, A1, A2, A3, A4)> &func) | |
template<typename T , typename U > | |
Callback (U *obj, R(T::*method)(A0, A1, A2, A3, A4)) | |
template<typename T , typename U > | |
Callback (const U *obj, R(T::*method)(A0, A1, A2, A3, A4) const) | |
template<typename T , typename U > | |
Callback (volatile U *obj, R(T::*method)(A0, A1, A2, A3, A4) volatile) | |
template<typename T , typename U > | |
Callback (const volatile U *obj, R(T::*method)(A0, A1, A2, A3, A4) const volatile) | |
template<typename T , typename U > | |
Callback (R(*func)(T *, A0, A1, A2, A3, A4), U *arg) | |
template<typename T , typename U > | |
Callback (R(*func)(const T *, A0, A1, A2, A3, A4), const U *arg) | |
template<typename T , typename U > | |
Callback (R(*func)(volatile T *, A0, A1, A2, A3, A4), volatile U *arg) | |
template<typename T , typename U > | |
Callback (R(*func)(const volatile T *, A0, A1, A2, A3, A4), const volatile U *arg) | |
template<typename F > | |
Callback (F f,) | |
template<typename F > | |
Callback (const F f,) | |
template<typename F > | |
Callback (volatile F f,) | |
template<typename F > | |
Callback (const volatile F f,) | |
template<typename T , typename U > | |
Callback (U *obj, R(*func)(T *, A0, A1, A2, A3, A4)) | |
template<typename T , typename U > | |
Callback (const U *obj, R(*func)(const T *, A0, A1, A2, A3, A4)) | |
template<typename T , typename U > | |
Callback (volatile U *obj, R(*func)(volatile T *, A0, A1, A2, A3, A4)) | |
template<typename T , typename U > | |
Callback (const volatile U *obj, R(*func)(const volatile T *, A0, A1, A2, A3, A4)) | |
~Callback () | |
void | attach (R(*func)(A0, A1, A2, A3, A4)) |
void | attach (const Callback< R(A0, A1, A2, A3, A4)> &func) |
template<typename T , typename U > | |
void | attach (U *obj, R(T::*method)(A0, A1, A2, A3, A4)) |
template<typename T , typename U > | |
void | attach (const U *obj, R(T::*method)(A0, A1, A2, A3, A4) const) |
template<typename T , typename U > | |
void | attach (volatile U *obj, R(T::*method)(A0, A1, A2, A3, A4) volatile) |
template<typename T , typename U > | |
void | attach (const volatile U *obj, R(T::*method)(A0, A1, A2, A3, A4) const volatile) |
template<typename T , typename U > | |
void | attach (R(*func)(T *, A0, A1, A2, A3, A4), U *arg) |
template<typename T , typename U > | |
void | attach (R(*func)(const T *, A0, A1, A2, A3, A4), const U *arg) |
template<typename T , typename U > | |
void | attach (R(*func)(volatile T *, A0, A1, A2, A3, A4), volatile U *arg) |
template<typename T , typename U > | |
void | attach (R(*func)(const volatile T *, A0, A1, A2, A3, A4), const volatile U *arg) |
template<typename F > | |
void | attach (F f,) |
template<typename F > | |
void | attach (const F f,) |
template<typename F > | |
void | attach (volatile F f,) |
template<typename F > | |
void | attach (const volatile F f,) |
template<typename T , typename U > | |
void | attach (U *obj, R(*func)(T *, A0, A1, A2, A3, A4)) |
template<typename T , typename U > | |
void | attach (const U *obj, R(*func)(const T *, A0, A1, A2, A3, A4)) |
template<typename T , typename U > | |
void | attach (volatile U *obj, R(*func)(volatile T *, A0, A1, A2, A3, A4)) |
template<typename T , typename U > | |
void | attach (const volatile U *obj, R(*func)(const volatile T *, A0, A1, A2, A3, A4)) |
Callback & | operator= (const Callback &that) |
R | call (A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) const |
R | operator() (A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) const |
operator bool () const |
静态公共成员函数 | |
static R | thunk (void *func, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) |
友元 | |
bool | operator== (const Callback &l, const Callback &r) |
bool | operator!= (const Callback &l, const Callback &r) |
带回调的串行直通示例
#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();
}
}
带回调的线程示例
Callback API 提供了一种将参数传递给生成线程的便捷方法。此示例在 Callback 中使用 C 函数指针。
#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 类的形式使用回调文档简介中讨论的所有内容。此示例在 Callback 中使用 C++ 类和方法。
#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());
}
}
调用回调
回调会使函数调用运算符重载,因此您可以像正常函数一样调用 Callback:
void run_timer_event(Callback<void(float)> on_timer) {
on_timer(1.0f);
}
唯一需要注意的是 Callback 类型具有空回调,就像空函数指针一样。未初始化的回调为 null,如果调用它们则断言。如果您希望呼叫始终成功,则需要先检查它是否为空。
void run_timer_event(Callback<void(float)> on_timer) {
if (on_timer) {
on_timer(1.0f);
}
}
Callback 类在 C++ 中称为 “具体类型”。也就是说,Callback 类足够轻量级,可以像 int,pointer 或其他基本类型一样传递。