回调函数:把需要调用的方法的指针pCallBackFuncX作为参数传递给一个函数UsrFunction,以便该UsrFunction函数在处理相似事件的时候可以灵活的使用不同的方法。

 

以在flash中存储有序的交易记录为例:

交易记录列表内容如下所示我们要对其排序然后存储到flash当中去。这个排序函数写作: int SortReclist(RECLIST_ST * reclist);

typedef struct {
char cityCode[] ; //城市代码 + 应用序列号
char usrName[];
unsigned char tradeTime[]; //交易时间【bcd】 年 月 日 时 分 秒
unsigned char TerminalCode[]; //终端硬件序列号
unsigned char reserve[];
} RECS_ST ;//交易记录 typedef struct {
unsigned char count[] ;
unsigned char max[] ;
unsigned char data[N_MAX_RECORD][SIZE_OF_RECS];// sizeof(RECS_ST); //要对这里的数据进行排序、去重。
unsigned char check ;
} RECLIST_ST;//交易记录列表

我们使用冒泡排序的方法对其中的数据进行排序,我们得到一组无序数据,我们不知道这组数据有多少个数据项、一个数据项多大、怎么比较他们的大小、如何交换数据项的位置。

我们可以设计如下,我们需要传入的参数不仅是数据p_data_in、n_elements、element_size,还有方法cmp_func、mem_swap

        bubble_sort(void* p_data_in ,                  //pointer to data to sort  待排列的数据
int n_elements , //number of elements 待排列的数据个数
int element_size, //size of each element == sizeof(RECS_ST) 数据宽度
(CALLBACK_AFC_DATA_CMP) cmp_func , //cmp_func: pointer to comparison function 判定其排列次序的方法,这个是根据需要变换的。
(CALLBACK_MEM_SWAP) mem_swap) ; //mem_swap: pointer to swap function or NULL 内存交换的方法
    typedef void (*CALLBACK_MEM_SWAP)(void *, void *, int n_bytes)  ;
    typedef int (*CALLBACK_AFC_DATA_CMP)(const void *, const void *) ;

bubble_sort的实现如下:
//ret==1: error
//ret==0: ok
int bubble_sort(void *base , //pointer to data to sort
int n_elements , //number of elements
int size_element , //size of each element
CALLBACK_AFC_DATA_CMP cmp_func ,//cmp_func: pointer to comparison function
CALLBACK_MEM_SWAP mem_swap )//mem_swap: pointer to swap function or NULL
{
int i, j, flag , cmp ;
if( base==0 || cmp_func==0 || mem_swap==0 ){
return 1 ;
} for (i=0; i<n_elements-1; i++)
{
flag = 0;
for (j=0; j<n_elements-1-i; j++)
{
cmp = cmp_func( ((char *)base+size_element*j ) , ((char *)base+size_element*(j+1)) ) ;
if ( cmp > 0 )
{
mem_swap( ((char *)base+j*size_element) , ((char *)base+(j+1)*size_element) , size_element );
flag = 1;
}
}
if ( !flag ) {
break ;
}
}
return 0;
}
int SortReclist(RECLIST_ST * reclist)
{
int ret;
unsigned char count[]; do{
memcpy(count , reclist->count , sizeof( count )); //这里是解决mdk对外部全局变量不能正确强转的解决办法,无视 bubble_sort(reclist->data , //pointer to data to sort
*(signed short*)count , //number of elements
sizeof( RECS_ST ) , //size of each element
(CALLBACK_AFC_DATA_CMP) reclistcmp , //cmp_func: pointer to comparison function
(CALLBACK_MEM_SWAP)mem_swap) ; //mem_swap: pointer to swap function or NULL
//暂且无视排序中去重的需求
}while(ret!=) ; return ;
}
到底采用何种方式来判断数据的大小,就根据实际需要了。下面是一个实现,只比较城市代码:
int reclistcmp(char *before ,char *next )
{
int ret ;
ret = memcmp(before ,next , ); //citycode[2] 简单判定
return ret ;
}

好处是,以回调函数的方式,在写主体框架时,可以不用知道某种功能的具体实现,而只是提出这个需求。

【写框架的人并不是完全不关心具体实现,不合理的框架设计导致具体功能无法按照给定的接口来实现。】

这样在处理具体业务时有更高的灵活性,这个功能的具体实现甚至可以交给其他人去完成。

//-----------------------------------------------------------------------------------------------------------------------------------------------//

另外,linux设备驱动函数注册也是回调的思想。linux内核并不知道我们具体设备的操作方式,它是这样对设备进行操作的,先规定操作函数的形式:

struct file_operations {
struct module *owner;
loff_t (*llseek) (struct file *, loff_t, int);
ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *
);
ssize_t (*aio_read) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
ssize_t (*aio_write) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
int (*readdir) (struct file *, void *, filldir_t);
unsigned int (*poll) (struct file *, struct poll_table_struct *);
int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long);//指定函数接口形式
long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
long (*compat_ioctl) (struct file *, unsigned int, unsigned long);
int (*mmap) (struct file *, struct vm_area_struct *);
int (*open) (struct inode *, struct file *);
int (*flush) (struct file *, fl_owner_t id);
int (*release) (struct inode *, struct file *);
int (*fsync) (struct file *, struct dentry *, int datasync);
int (*aio_fsync) (struct kiocb *, int datasync);
int (*fasync) (int, struct file *, int);
int (*lock) (struct file *, int, struct file_lock *);
ssize_t (*sendfile) (struct file *, loff_t *, size_t, read_actor_t, void *);
ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int);
unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
int (*check_flags)(int);
int (*dir_notify)(struct file *filp, unsigned long arg);
int (*flock) (struct file *, int, struct file_lock *);
ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int);
ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int);
};

然后驱动设计者按照规定的形式实现ioctl。

/* 应用程序对设备文件/dev/leds执行ioctl(...)时,
* 就会调用s3c24xx_leds_ioctl函数
*/
static int s3c24xx_leds_ioctl(
struct inode *inode,
struct file *file,
unsigned int cmd,//ON / OFF
unsigned long arg)//n_led
{
if (arg > ) {
return -EINVAL;
} switch(cmd) {
case IOCTL_LED_ON:
// 设置指定引脚的输出电平为0
s3c2410_gpio_setpin(led_table[arg], );
return ; case IOCTL_LED_OFF:
// 设置指定引脚的输出电平为1
s3c2410_gpio_setpin(led_table[arg], );
return ; default:
return -EINVAL;
}
}

驱动设计者再注册操作集,包括了ioctl。

static struct file_operations s3c24xx_leds_fops = {
.owner = THIS_MODULE, /* 这是一个宏,推向编译模块时自动创建的__this_module变量 */
.open = s3c24xx_leds_open,
.ioctl = s3c24xx_leds_ioctl,
}; //in moudle_init:
ret = register_chrdev(LED_MAJOR, DEVICE_NAME, &s3c24xx_leds_fops);

这样,在打开操作设备时,系统使用到了驱动设计者的设备操作方法。

扩展阅读:

1.回调机制

  http://blog.sina.cn/dpool/blog/s/blog_77c632410101cjty.html

2.简单的c++回调函数设计方法(一)

  回调实现分层设计。

  http://blog.chinaunix.net/uid-21222282-id-1829257.html

c语言 ,回调函数[个人理解]的更多相关文章

  1. 对c语言回调函数的理解

    对于回调函数,可以简单的理解为一种特别的函数调用方法,我们可以对比一下回调函数与普通函数在调用方法上的区别. 1. 普通函数调用 一般为实现方在其函数体执行过程中直接调用. 代码示例: #includ ...

  2. js回调函数(callback)理解

    Mark! js学习 不喜欢js,但是喜欢jquery,不解释. 自学jquery的时候,看到一英文词(Callback),顿时背部隐隐冒冷汗.迅速google之,发现原来中文翻译成回调.也就是回调函 ...

  3. js回调函数的理解

    js回调函数(callback)理解 Mark! 讲之前说一句 function say(){ alert(,,,,,,,,) } var say=function (){ alert(,,,,,,, ...

  4. 回调函数透彻理解Java

    http://blog.csdn.net/allen_zhao_2012/article/details/8056665 回调函数透彻理解Java 标签: classjavastringinterfa ...

  5. js中的回调函数的理解和使用方法

    js中的回调函数的理解和使用方法 一. 回调函数的作用 js代码会至上而下一条线执行下去,但是有时候我们需要等到一个操作结束之后再进行下一个操作,这时候就需要用到回调函数. 二. 回调函数的解释 因为 ...

  6. JavaScript callback function 回调函数的理解

    来源于:http://mao.li/javascript/javascript-callback-function/ 看到segmentfault上的这个问题 JavaScript 回调函数怎么理解, ...

  7. 转·带你用实例理解C语言回调函数

    原文出处:https://segmentfault.com/a/1190000008293902?utm_source=tag-newest 前言: 如不懂函数指针,请先查阅关于函数指针内容的资料(h ...

  8. 对于Python中回调函数的理解

    关于回调函数,网上有很多说明和各种解释,多数在尝试用语言描述.我认为,如果对各个角色之间的关系不清楚,如果没有相关的编程需求,那么语言便非常无力,很难理解. 这是360百科的解释: 在计算机程序设计中 ...

  9. C语言回调函数详解

    1. 什么是回调函数? 回调函数,光听名字就比普通函数要高大上一些,那到底什么是回调函数呢?恕我读得书少,没有在那本书上看到关于回调函数的定义.我在百度上搜了一下,发现众说纷纭,有很大一部分都是使用类 ...

随机推荐

  1. POJ_1698_Alice's Chance

    #include <iostream> #include <queue> #include <climits> #include <cstring> u ...

  2. Android 开发笔记“浅谈DDMS视图”

    DDMS 的全称是Dalvik Debug Monitor Service,即Dalvik调试监控服务,是一个可视化的调试监控工具.它主要是对系统运行后台日志的监控,还有系统线程,模拟器状态的监控.此 ...

  3. 用javascirpt画个太极

    偶然看到用代码画太极,感觉很有趣,用JS写了一个 过程很简单,画了张图,应该一看就懂了 代码也很简单,如下,注释很多 function TaiJi(r,canvas){ this.r = r; thi ...

  4. C++的二进制兼容问题(以QT为例)

    二进制不兼容带来的问题(需要重新编译库文件,以前编译的失效): http://my.oschina.net/lieefu/blog/505363?fromerr=f5jn7rct 二进制不兼容的原理: ...

  5. 求最大值最小值的方法 时间复杂度O(n)

    #include<iostream> #include <iostream> #include <bitset> #include <ctime> us ...

  6. 可以放在html代码中的自动跳转代码

    可以放在html代码中的自动跳转代码 有3种方法可以实现html的页面跳转,1,refresh   2,onload事件中加入代码  3,js实现 1.<html><body> ...

  7. 常用 API

    运行 Java 程序的参数.使用 Scanner 获取键盘输入.使用 BufferedReader 获取键盘输入.System类.Runtime类.Object类.Java 7新增的 Objects ...

  8. VS2010 简单实用快捷键

    VS2010 简单实用快捷键 1). Ctrl+H: 替换 2). Ctrl+F: 查找 3). F5: 启动调试 4). CTRL + F7 生成编译 5). Ctrl+F5: 开始执行(不调试) ...

  9. Android学习笔记(十四)——在执行时加入碎片(附源代码)

    在执行时加入碎片 点击获取源代码 将UI切割为多个可配置的部分是碎片的优势之中的一个,但其真正强大之处在于可在执行时动态地把它们加入到活动中. 1.使用上一篇创建的Fragments项目,在main. ...

  10. [置顶] 局部加权回归、最小二乘的概率解释、逻辑斯蒂回归、感知器算法——斯坦福ML公开课笔记3

    转载请注明:http://blog.csdn.net/xinzhangyanxiang/article/details/9113681 最近在看Ng的机器学习公开课,Ng的讲法循循善诱,感觉提高了不少 ...