回调函数在日常开发中使用广泛,什么是回调函数,为什么要使用回调函数,如何使用回调函数,本文将结合一个例子说明。

什么是回调函数?

回调函数也是函数,通俗的来说回调函数是由开发者A定义,另个开发者B实现,并在A实现的函数中调用的函数。

为什么使用回调函数?

代码设置都是分层设计的,也就是模块化设计,特别是嵌入式的开发。代码的编码都是分工合作的,每个人负责不同的部分。而不同的层次之间也有相互依赖。假如模块A的数据如何传给另一个模块B,模块B如何处理数据,模块A是不关心的。这就需要模块B将自己的处理函数给模块A,这就是所谓的 函数注册。这个注册的函数是回调注册函数,被注册的函数就是回调函数。

回调函数实现方式?

回调函数实现方式就是将函数的指针作为注册函数的参数注册给调用者,调用者使用函数指针(一般为全局函数指针)接收该回调函数。这个过程一般是注册回调的过程。调用者在没有接收到这个回调函数之前,直接先使用全局指针完成函数调用,所以说代码运行之前,必须要完成函数的注册。不然找不到该函数,会导致空指针错误。

例子:假如要完成温湿度采集和处理,如何实现?考虑到模块化设计和分工,甲完成温度的采集,乙完成湿度的采集,丙处理这个两个数据。丁负责写整个应用将三个部分串起来。其中甲乙的数据就可以使用回调函数传输给丙处理。开发之前需要甲乙需要定义各种头文件里面提供自己函数声明和回调函数的声明,以及回调函数的注册方法。

甲:负责temperature 采集。

乙:负责humidity采集。

丙:负责数据处理。

丁:负责应用程序的开发。

在linux环境下使用多线程的方式模拟,线程之前使用管道通信实现。

甲同学实现部分:

头文件

temperature_drive.h

#ifndef _DRIVE_TMP_H__
#define _DRIVE_TMP_H__
typedef int (*callback_fuction)(int a,char *data); //函数指针定义
int register_callback_func_tmp(callback_fuction callback);
void start_tem_drive(pthread_t *thread);
#endif

C文件

temperature_drive.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include "temperature_drive.h"
pthread_mutex_t mutex;
callback_fuction g_callback;
//注册回调函数
int register_callback_func_tmp(callback_fuction callback)
{g_callback = callback;
}void* callback_thread_tem(void *p1)
{while(1){int static num = 0;if(NULL == g_callback){printf("WAITE REGIST! \n");exit(0);}sleep(2);pthread_mutex_lock(&mutex);g_callback(num,"temperature");//调用回调函数将数据返回到回调函数的实现方,也就是丙num++;pthread_mutex_unlock(&mutex);}
}void start_tem_drive(pthread_t *thread)
{//创建线程pthread_t pthread;pthread_create(&pthread,NULL,callback_thread_tem,NULL);*thread = pthread;//pthread_join(pthread,NULL);sleep(1);
}

乙同学实现部分

头文件

humidity_drive.h

#ifndef _HUMIDITY_H__
#define _HUMIDITY_H__typedef int (*callback_fuction_hum)(char *data); //函数指针定义
int register_callback_func_hum(callback_fuction_hum callback);
void start_hum_drive(pthread_t *thread);
#endif

C文件

humidity_drive.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include "humidity_drive.h"
extern pthread_mutex_t mutex;
callback_fuction_hum g_callback_humidity;
//注册回调函数
int register_callback_func_hum(callback_fuction_hum callback)
{g_callback_humidity = callback;
}void* callback_thread_hum(void *p1)
{while(1){if(NULL == g_callback_humidity){printf("WAITE REGIST! \n");exit(0);}sleep(3);pthread_mutex_lock(&mutex);g_callback_humidity("humidity");//通过回调函数将数据返回pthread_mutex_unlock(&mutex);}
}void start_hum_drive(pthread_t *thread)
{//创建线程pthread_t pthread;pthread_create(&pthread,NULL,callback_thread_hum,NULL);*thread = pthread;//pthread_join(pthread,NULL);sleep(1);
}

丙同学部分

头文件

data_handle.h

#ifndef _DATA_HANDLE_H__
#define _DATA_HANDLE_H__
void data_handle_init(void);
void start_data_handle(pthread_t *thread);
#endif

C文件

data_handle.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include "data_handle.h"
#include "temperature_drive.h"
#include "humidity_drive.h"
//注册回调
int pip_ios_fd[2] ;
int handle_tem_data_callback(int num, char *data)  //实现具体温度处理的回调函数
{printf("handle_tem_data_callback\n");int wret = write(pip_ios_fd[1], data, sizeof(data));printf("num%d\n",num);return 0;}
int handle_hum_data_callback(char *data) //实现具体的湿度处理的回调函数
{printf("handle_hum_data_callback\n");int wret = write(pip_ios_fd[1], data, sizeof(data));
}void* data_handle_thread(void *p1)
{while(1){char data[10];int ret = read(pip_ios_fd[0], data, sizeof(data));//管道为空阻塞printf("rev data len:%d,data is:%s\n",ret,data);//集中处理所有收到的数据}
}
void data_handle_init()
{register_callback_func_tmp(handle_tem_data_callback);//调用注册回调函数register_callback_func_hum(handle_hum_data_callback);
}
void start_data_handle(pthread_t *thread)
{//创建线程int pip_ret = pipe(pip_ios_fd);pthread_t pthread;pthread_create(&pthread,NULL,data_handle_thread,NULL);//pthread_join(pthread,NULL);*thread = pthread;sleep(1);
}

丁同学应用部分:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include "temperature_drive.h"
#include "humidity_drive.h"
#include "data_handle.h"int main()
{/*先调用初始化,为了先注册回调函数*/pthread_t thread,thread1,thread2;data_handle_init();/*启动温度检测*/start_tem_drive(&thread);/*启动湿度检测*/start_hum_drive(&thread1);/*启动数据处理*/start_data_handle(&thread2);pthread_join(thread,NULL);pthread_join(thread1,NULL);pthread_join(thread2,NULL);return 0;
}

写个简单的makefile

UGW_INC += -I $(pwd) ./
CC = gcc
UGW_SRCS = $(wildcard *.c)
UGW_OBJS = $(patsubst %.c,%.o, $(UGW_SRCS))all: $(UGW_OBJS)
%.o:%.c$(CC) -c  -o $@ -MD $< $(UGW_INC)clean:-rm -f *.o-rm -f *.d

一键make,运行。ok,搞定。demo虽小,五脏俱全。通过demo,可以了解,代码的分层设计,代码的分工,回调函数的使用,线程间通信方式(管道)。还有改进的空间,有时间优化丙管道阻塞读,改为select监听非阻塞方式。作者水平有限,有错误欢迎指正。

回调函数介绍和使用方法以及使用例子相关推荐

  1. java如何构造ajax回调参数,jQuery实现ajax回调函数带入参数的方法示例

    本文实例讲述了jQuery实现ajax回调函数带入参数的方法.分享给大家供大家参考,具体如下: 不带参数的写法: function pass(htmlId,auditingFlag){ var url ...

  2. php函数的默认值,php函数指定默认值方法的小例子

    php函数指定默认值方法的小例子 本节内容: php函数指定默认值 在php编程中,为自定义函数设定默认值,当用户调用该函数时,如果不给参数指定值,参数会用默认值顶替. 例1, 复制代码 代码如下: ...

  3. php中in array函数_in_array函数介绍与使用方法详解

    PHP的性能一直在提高.然而,若是用的不恰当,或是一个不留神,还是可能会踩到PHP内部实现方面的坑的.我在前几天的一个性能问题上就碰到了PHP的性能一直在提高.然而,若是用的不恰当,或是一个不留神,还 ...

  4. c语言flip用法,【杂谈】flip函数介绍与使用方法详解

    实例反转数组中的键名和对应关联的键值:<?php $a1=array("a"=>"red","b"=>"gree ...

  5. Callback回调函数介绍(C语言)

    目录 1. 回调函数的定义 2. 为什么要用回调函数 3. 怎么用回调函数 3.1 怎么使用没有参数的回调函数 3.2 怎么使用带参数的回调函数 1. 回调函数的定义 最近在工作中经常用到回调函数ca ...

  6. python回调函数实例详解_python 简单的例子下详解回调函数

    回调的英文定义: A callback is a function that is passed as an argument to another function and is executed ...

  7. python中sleep函数用法_sleep函数函数介绍与使用方法详解

    在一些竞猜的网站中,如果我们需要做一个定时执行的功能,比如有一道题,在十秒之内要完成,否则显示"您已超时",如果完成,则跳转到下一道题上面,而这中间有一个十秒的停顿,这样的功能是怎 ...

  8. php fopen函数php,fopen函数介绍与使用方法详解

    在我们的PHP开发中会经常遇到fopen()和file_get_contents(),相信很多同学都发现这两个函数基本上都差不多,那么我们今天就来讲讲php fopen()和file_get_cont ...

  9. php+die(.)函数,die函数介绍与使用方法详解

    本篇文章是对php中die(),exit(),return的区别进行了详细的分析介绍,需要的朋友参考下die()停止程序运行,输出内容exit是停止程序运行,不输出内容return是返回值die是遇到 ...

最新文章

  1. 【透明版九宫格背景图片】仅依靠background的几个属性组合搭配出酷炫的透明背景卡片效果→适用于大数据可视化、数据大屏展示页面
  2. 聚焦触宝反侵权事件:中国创业者用什么护航海外市场大门
  3. java环境变量_java环境变量
  4. OpenCV人脸识别LBPH算法源码分析
  5. ORA-29861: 域索引标记为 LOADING/FAILED/UNUSABLE
  6. mac下flink集群安装
  7. java 将 ResultSet 转化为 json格式
  8. 【LOJ119】单源最短路 模板
  9. SQL反模式学习笔记1 开篇
  10. 20200723每日一句
  11. 关于码云的一些基本知识_关于葡萄酒,你必须知道的一些基础知识
  12. 三思笔记_在使用buildconfig调试之前要三思
  13. abaqus6.14安装教程 如何设置中文
  14. 【被网上巨坑了】 win10+php5.6-ts-vc11-x64配置imagick的经历
  15. 如何进行网站挂马检测?怎样清除挂马?
  16. 计算机网络知识点总结——第三章数据链路层
  17. 微软手环2服务器,数据狂的最爱 微软手环2评测
  18. python中的统计模型库——statsmodels
  19. 数据库缓存服务—Redis配置与优化
  20. 一仓库失窃,四管理员被传讯_如何找到丢失或失窃的Android手机

热门文章

  1. 二手车电商需要“贝壳”?
  2. sql—窗口函数rank()、dense_rank()的使用
  3. 【python编程】利用python获取服务器时间
  4. 前端基础01:HTML
  5. SNMP网管NAT穿透的问题
  6. 【ODX介绍】-3-ODX文件结构分解
  7. C语言源代码系列-管理系统之职工信息管理系统
  8. C# 使用NModbus 多Slave站编程方法
  9. 【技术认证题库】SCCA理论aDesk-1考试【初级】
  10. 华为开发者大会主题演讲:图形引擎服务开启图形渲染的无限可能