C/C++回调函数简要介绍

分享到:

1、引子

在C/C++里面有个非常给力的库函数qsort,相信大家都用过。他的函数原型如下:

void qsort(void *base,size_tnmemb,size_tsize,  int(*compar)(constvoid*, constvoid*));

使用的时候需要传递需要排序的数组base, 数组数目nmeb, 每个数组大小size,以及我们比较自定义的回调函数:compar.

2、概念

如compar所示,如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。

和回调函数相对,普通函数调用一般为同步调用,即A模块阻塞调用B模块函数,B模块执行完毕之后会讲结果返回给A模块。

回调函数则不同。A模块定义一个回调函数C,将函数指针C传给B模块作为参数。在调用B模块之后,B模块会根据一定的条件触发回调C,进而重新调用模块A的函数。

这样模块B就不用关心回调函数自己的具体实现,这样可以是系统架构更加清晰,可以提高系统的可扩展性。

3、举例

现在我们有个模块叫callback模块。callback模块会接受主函数main传来的a,b,回调函数c.

如果a==100,那么就返回10000,否则就使用我们的回调函数,执行c(a,b),并返回。

具体如下所示:

3.1、通用头文件 pub.h

这里主要定义了一个函数指针。

函数原型为 int myfoo(int, int); 

如果有疑问,请自行Google or Baidu.

/***************************************************************************
 *
 * Copyright (c) 2014 liujun&&baidu. inc All Rights Reserved
 *
 **************************************************************************/
/*
 * @filename:  pub.h
 * @version:  1.0
 * @date : 2014/01/28 14时44分05秒
 * @author:  liujun (liujun0923@zju.edu.cn)
 * @breif:  
 */
#ifndef  PUB_INC
#define  PUB_INC
#include<stdio.h>
//定义一个回调函数,返回为int, 参数为int,int
typedef int(*myfoo)(int, int);
#endif   /* ----- #ifndef PUB_INC  ----- */

 

3.2、callback模块

头文件callback.h: 主要定义了一个结构体,包括a,b,回调函数foo。同时有一个执行函数process.

/***************************************************************************
 *
 * Copyright (c) 2014 liujun&&baidu. inc All Rights Reserved
 *
 **************************************************************************/
/*
 * @filename:  callback.h
 * @version:  1.0
 * @date : 2014/01/28 14时46分31秒
 * @author:  liujun (liujun0923@zju.edu.cn)
 * @breif:  
 */
#ifndef  CALLBACK_INC
#define  CALLBACK_INC
#include "pub.h"
typedef struct _foo_struct_t{
    int a;
    int b;
    myfoo foo;
}foo_struct_t;
int process(foo_struct_t* data);
#endif   /* ----- #ifndef CALLBACK_INC  ----- */


执行函数callback.c: 如果a=100,那么返回10000,否则使用回调函数来执行

/***************************************************************************
 *
 * Copyright (c) 2014 liujun&&baidu. inc All Rights Reserved
 *
 **************************************************************************/
/*
 * @filename:  callback.c
 * @version:  1.0
 * @date : 2014/01/28 14时48分26秒
 * @author:  liujun (liujun0923@zju.edu.cn)
 * @breif:  
 */
#include "callback.h"
int process(foo_struct_t* data)
{
	int res;
	//这里你可以做很多事情。
//这里你可以用主函数传来的函数指针来进行回调
	if( data->a == 100)
	{
res = 10000;
	}
	else
	{
res =  data->foo(data->a, data->b);
	}
	//你还是可以做很多事情
	return res;
}

 

3.3、main模块

main.c: 从命令行接受参数a,b, 然后将a,b以及myfun函数地址一起参入模块callback。

/***************************************************************************
 *
 * Copyright (c) 2014 liujun&&baidu. inc All Rights Reserved
 *
 **************************************************************************/
/*
 * @filename:  main.c
 * @version:  1.0
 * @date : 2014/01/28 14时52分48秒
 * @author:  liujun (liujun0923@zju.edu.cn)
 * @breif:  
 */
#include "pub.h"
#include "callback.h"
#include <stdlib.h>
int myfun(int a, int b)
{
    return a+b;
}
int main(int argc, char** argv)
{
    foo_struct_t* data = (foo_struct_t*)malloc(sizeof(foo_struct_t));
    data->a = atoi(argv[1]);
    data->b = atoi(argv[2]);
    data->foo = myfun;    
    int res = process(data);
    printf("after callback is %d\n", res);
    return 0;
}

 

3.4、Makefile

先生存libcallback,然后生成可执行文件。

main: main.c libcallback
	gcc -g main.c -I. -L. -lcallback -o main
libcallback:callback.h callback.c pub.h
	gcc -g -c callback.h callback.c pub.h
	ar -r libcallback.a callback.o
clean:
	rm *.gch
	rm *.o
	rm *.a
	rm main

 

3.5、执行结果

liujun@ubuntu:~/test/callback$ ./main  100 200
after callback is 10000
liujun@ubuntu:~/test/callback$ ./main  50 200
after callback is 250

可以看到达到我们预期效果。

来自:http://my.oschina.net/jungleliu0923/blog/198151
昵    称:
验证码:

相关文档:

  • C语言高级编程库:Cello
    Cello的高级结构受到了Haskell的启发;而语法与语义受到Python,Obj-C的启发。它不是关于C语言的面向对象的,而是提供一种工具将C语言转...
  • C++书籍推荐
    本文内容来自国外著名编程问答网站Stackoverflow评选的C++推荐书单!推荐大家看原版英文,但这些书大部分也都有中文版!...
  • 采用纯C语言进行面向对象编程的模板 - OOC-GCC
    这是一个模板,是一些宏的集合,针对跨平台的GCC设计[0.11版以后的与VC9编译器兼容]...
  • 内存分配模块 nedmalloc
    nedmalloc 是一个可选的malloc内存分配的实现,主要是适应多线程无锁操作,基于 dlmalloc 2.8.3 。...
  • 编码格式转换库 libiconv
    iconv是一个计算机程序以及一套应用程序编程接口的名称。它的作用是在多种国际编码格式之间进行文本内码的转换。...
  • 4个函数实现的C编译器:C4
    4个函数实现的c编译器,大约500行。基本上已经比较完备了,可以自己编译自己。...
  • C++ 库:Libexecstream
    Libexecstream 是 C++ 库,允许你运行一个子进程并且获取进程的输入,输出和错误,类似标准 C++ 流。...
  • WEB开发的C++类库 WebAppLib
    WebAppLib是一系列主要用于类Unix操作系统环境下 WEB开发的C++类库。...
  • 使用 C++ 的 StringBuilder 提升 4350% 的性能
    经常出现客户端打电话抱怨说:你们的程序慢如蜗牛。你开始检查可能的疑点:文件IO,数据库访问速度,甚至查看web服务。 但是这些可...
  • 开发C++应用的实用工具包:fplutil
    fplutil是一组小的库和工具,当开发Android和其它平台的应用时非常实用。...
  • C/C++编译器 GCC
    GCC(GNU Compiler Collection,GNU编译器套装),是一套由 GNU 开发的编程语言编译器。它是一套以 GPL 及 LGPL 许可证所发行的自由软件,也是 GN...
  • C++对象池:C++ ResourcePool
    C++ ResourcePool 是一个C++语言开发的通用的对象池,提供一个独立的类型无关的API。...
  • C++ 工具类库:Moost
     Last.fm 的音乐信息检索团队近日开源了 moost 工具,这是该团队在产品开发过程中使用的 C++ 实用程序的集合。...
  • 开发者都应该使用的10个C++11特性
    在C++11新标准中,语言本身和标准库都增加了很多新内容,本文只涉及了一些皮毛。不过我相信这些新特性当中有一些,应该成为所有C++...
  • 免费的C/C++的线程库
    免费的C/C++的线程库...
  • C++操作SQLite数据库
    在使用C++操作SQLite之前,需要获得sqlite3.h,sqlite3.lib,sqlite3.dll,大家可以在这里下载。并将这3个文件导入VC++工程中。其中sqlite3.dll文件...
  • C语言的SPDY开发包 libspdy
    libspdy 是 C 语言实现对 SPDY 协议支持的库。只需依赖 zlib 包...
  • C++微量级软件开发包:Micro-Development-Kit
    mdk(Micro-Development-Kit)微量级软件开发包,使用c++开发,是一个跨平台的开发包,支持linux32/linux64/win32/win64的类库,提供几个常用类,主要...
  • 非常精简的开源 C 协程库:Protothreads
    开源 C 协程库 protothreads。这是一个全部用 ANSI C 写成的库,之所以称为“蝇量级”的,就是说,实现已经不能再精简了,几乎就是原语级...
  • C++ 并发编程指南
    传播知识,介绍 C++ 并发编程。目前国内还没有一本完整介绍 C++11 并发编程的中文书籍,希望本书可以帮助广大的 C++ 开发者学习并发编...