8.21 模块间通信(中):回调函数
函数调用接口
普通函数调用
回调函数
消息通信接口
异步通信:消息、信号量、中断、事件驱动
函数调用
通信方式
参数传递
返回值
单向调用
函数调用例程
main.c
/************************************************
* Filename: main.c
* Author: litao.wang
* Description:
* Create: 2018-01-12 00:05:46
* Last Modified: 2018-06-14 21:25:24
*************************************************/
#include<stdio.h>
int send_data(char *buf,int len);
int main(void)
{
char buffer[10]={1,2,3,4,5,6,7,8,9,0};
int return_data;
return_data = send_data(buffer,10);
printf("send data len:%d\n",return_data);
return 0;
}
module.c
/************************************************
* Filename: module.c
* Author: litao.wang
* Description:
* Create: 2018-01-12 00:07:13
* Last Modified: 2018-06-14 21:24:58
*************************************************/
#include<stdio.h>
int send_data(char *buf,int len)
{
char data[100];
int i;
for(i=0;i<len;i++)
data[i] = buf[i];
for(i=0;i<len;i++)
printf("received data[%d] = %d\n",i,data[i]);
return len;
}
回调函数
双向通信
- 定义
– 一般应用程序直接调用系统、库、底层模块的API
– 如果反过来,用户写一个函数,让系统直接调用该函数,
称为回调。 - 特点
– 控制反转
– 好莱坞原则
– do not call me, I will call you
回调函数例程
app.c
/************************************************
* Filename: app.c
* Author: litao.wang
* Description:
* Create: 2018-01-12 01:37:47
* Last Modified: 2018-06-14 15:46:15
*************************************************/
#include<stdio.h>
#include"module.h"
void func1(void)
{
printf("func1...\n");
}
void func2(void)
{
printf("func2...\n");
}
int main(void)
{
runcallback(func1);
runcallback(func2);
return 0;
}
module.c
/************************************************
* Filename: module.c
* Author: litao.wang
* Description:
* Create: 2018-06-14 15:44:48
* Last Modified: 2018-06-14 15:45:49
*************************************************/
void runcallback(void (*fp)(void))
{
fp();
}
module.h
/************************************************
* Filename: module.h
* Author: litao.wang
* Description:
* Create: 2018-06-14 15:45:27
* Last Modified: 2018-06-14 21:27:02
*************************************************/
#ifndef __RUNCALLBACK__H
#define __RUNCALLBACK__H
void runcallback(void (*fp)(void));
#endif
回调函数解耦
依赖与耦合
函数调用、变量引用
依赖倒置原则
Robert Martin
高层模块不应该依赖低层模块,它们共同依赖于一个抽象
抽象不能依赖具象,具象依赖于抽象
块间解耦:两个模块之间定义一个抽象接口
回调函数解耦例程
回调函数不需要多次实现
app.c
/************************************************
* Filename: app.c
* Author: litao.wang
* Description:
* Create: 2018-06-14 15:57:35
* Last Modified: 2018-06-14 17:04:11
*************************************************/
#include<stdio.h>
#include"device_manager.h"
int sd_read(void)
{
printf("sd read data...\n");
return 10;
}
int udisk_read(void)
{
printf("udisk read data...\n");
return 20;
}
struct storage_device sd={ //按照回调模块定义好的结构体填写
"sdcard",sd_read
};
struct storage_device udisk={ //按照回调模块定义好的结构体填写
"udisk",udisk_read
};
int main(void)
{
register_device(sd);
register_device(udisk);
read_device("udisk");
read_device("udisk");
read_device("uk");
read_device("sdcard");
read_device("sdcard");
return 0;
}
device_manager.c
/************************************************
* Filename: device_manager.c
* Author: litao.wang
* Description:
* Create: 2018-06-14 15:59:06
* Last Modified: 2018-06-14 17:20:01
*************************************************/
#include<stdio.h>
#include<string.h>
#include"device_manager.h"
struct storage_device device_list[100]={0};
unsigned char num;
int register_device(struct storage_device dev)
{
device_list[num++] = dev;
return 0;
}
//注册为数组
int read_device(char *device_name)
{
int i;
for(i=0;i<100;i++)
{
if (!strcmp(device_name,device_list[i].name))
break;
}
if(i==100)
{
printf("read error! can't find device: %s\n",device_name);
return -1;
}
return device_list[i].read();
}
/************************************************
* Filename: device_manager.h
* Author: litao.wang
* Description:
* Create: 2018-06-14 16:02:35
* Last Modified: 2018-06-14 17:44:39
*************************************************/
#ifndef __STORAGE_DEVICE__H
#define __STORAGE_DEVICE__H
typedef int (*read_fp)(void);
struct storage_device{
char name[20];
// int (*read)(void);
read_fp read;
};
extern int register_device(struct storage_device dev);
extern int read_device(char *device_name);
#endif