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

来源:互联网 发布:17173魔兽世界数据库 编辑:程序博客网 时间:2024/05/20 23:36

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

摘自:http://my.oschina.net/jungleliu0923/blog/198151?from=20140216

目录[-]

  • 1、引子
  • 2、概念
  • 3、举例
  • 3.1、通用头文件 pub.h
  • 3.2、callback模块
  • 3.3、main模块
  • 3.4、Makefile
  • 3.5、执行结果
  •     

    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.

    view source
    print?
    01/***************************************************************************
    02 *
    03 * Copyright (c) 2014 liujun&&baidu. inc All Rights Reserved
    04 *
    05 **************************************************************************/
    06 
    07/*
    08 * @filename:  pub.h
    09 * @version:  1.0
    10 * @date : 2014/01/28 14时44分05秒
    11 * @author:  liujun (liujun0923@zju.edu.cn)
    12 * @breif:  
    13 */
    14 
    15#ifndef  PUB_INC
    16#define  PUB_INC
    17 
    18#include<stdio.h>
    19 
    20//定义一个回调函数,返回为int, 参数为int,int
    21typedef int(*myfoo)(intint);
    22 
    23#endif   /* ----- #ifndef PUB_INC  ----- */


    3.2、callback模块

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

    view source
    print?
    01/***************************************************************************
    02 *
    03 * Copyright (c) 2014 liujun&&baidu. inc All Rights Reserved
    04 *
    05 **************************************************************************/
    06 
    07/*
    08 * @filename:  callback.h
    09 * @version:  1.0
    10 * @date : 2014/01/28 14时46分31秒
    11 * @author:  liujun (liujun0923@zju.edu.cn)
    12 * @breif:  
    13 */
    14 
    15 
    16#ifndef  CALLBACK_INC
    17#define  CALLBACK_INC
    18 
    19#include "pub.h"
    20 
    21typedef struct _foo_struct_t{
    22    int a;
    23    int b;
    24    myfoo foo;
    25}foo_struct_t;
    26 
    27int process(foo_struct_t* data);
    28 
    29#endif   /* ----- #ifndef CALLBACK_INC  ----- */


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

    view source
    print?
    01/***************************************************************************
    02 *
    03 * Copyright (c) 2014 liujun&&baidu. inc All Rights Reserved
    04 *
    05 **************************************************************************/
    06 
    07/*
    08 * @filename:  callback.c
    09 * @version:  1.0
    10 * @date : 2014/01/28 14时48分26秒
    11 * @author:  liujun (liujun0923@zju.edu.cn)
    12 * @breif:  
    13 */
    14 
    15#include "callback.h"
    16 
    17int process(foo_struct_t* data)
    18{
    19    int res;
    20    //这里你可以做很多事情。
    21 
    22    //这里你可以用主函数传来的函数指针来进行回调
    23    if( data->a == 100)
    24    {
    25        res = 10000;
    26    }
    27    else
    28    {
    29        res =  data->foo(data->a, data->b);
    30    }
    31    //你还是可以做很多事情
    32    return res;
    33}


    3.3、main模块

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

    view source
    print?
    01/***************************************************************************
    02 *
    03 * Copyright (c) 2014 liujun&&baidu. inc All Rights Reserved
    04 *
    05 **************************************************************************/
    06 
    07/*
    08 * @filename:  main.c
    09 * @version:  1.0
    10 * @date : 2014/01/28 14时52分48秒
    11 * @author:  liujun (liujun0923@zju.edu.cn)
    12 * @breif:  
    13 */
    14 
    15#include "pub.h"
    16#include "callback.h"
    17#include <stdlib.h>
    18 
    19int myfun(int a, int b)
    20{
    21    return a+b;
    22}
    23 
    24int main(int argc, char** argv)
    25{
    26    foo_struct_t* data = (foo_struct_t*)malloc(sizeof(foo_struct_t));
    27    data->a = atoi(argv[1]);
    28    data->b = atoi(argv[2]);
    29    data->foo = myfun;    
    30    int res = process(data);
    31    printf("after callback is %d\n", res);
    32    free(data);
    33    return 0;
    34}


    3.4、Makefile

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

    main: main.c libcallbackgcc -g main.c -I. -L. -lcallback -o mainlibcallback:callback.h callback.c pub.hgcc -g -c callback.h callback.c pub.har -r libcallback.a callback.oclean:rm *.gchrm *.orm *.arm main


    3.5、执行结果

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

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


    最后给个具体的例子:

    https://github.com/jungleliu0923/myserver

    客户端C连接例子部分代码如下,其中mys_server_set_callback就是使用回调。

    view source
    print?
    01int main()
    02{
    03    my_log_init("./log""sample.log""sample.log.wf", 16);
    04    server = my_server_create("./conf/""myserver.conf""sample");
    05    if(server == NULL)
    06    {
    07        cout << "create sever fail\n";
    08        return -1;
    09    }
    10    my_server_set_callback(server, my_callback);
    11    my_server_run(server);
    12    return 0;
    13}
    0 0