回调函数的参数是怎么传的_回调函数与其回调机制

回调函数与其机制:

## 是什么?

一句话概括:A调B,并把C当参数传给B,B运行,再调用了充当参数的C。

如下图:

31fa1020edcb1373a4c2c4e4dbb9027c.png

解析:应用层的函数A调底层的函数B,顺便把应用层的函数C当参数传给B,而B在底层执行的时候,需要回到应用层调用C,这个过程就叫回调,而函数C就是回调函数。

## 为什么?

就拿最常用的理由来说,假设甲和乙分别做镜头移动控制和镜头自动对焦,两个人,分开写代码,这个时候,乙需要用到镜头的位置信息,聚焦情况等,而这些东西是由甲所能够直接获得的,乙也不知道,那么,怎么办?

可能有人会说:“过去问甲啊,让它把代码发给你,然后你再复制过去,加几个库文件什么的,直接在你那里获取了这些信息就行了啊!”

可能有人人会说:“你让甲把获取信息的接口给你,你执行的时候再调用那个接口,回到甲那里拿数据即可。”

换做是你,你会怎么办?

很明显,当然第二种方法更好,看下面分析:

①代码复杂程度:第一种方法,需要拿到甲的代码,然后才能获取到信息,这无疑是增加了代码量;而后者,只需拿甲的接口,即可获得信息;

②模块的耦合性:第一种方法,需要在乙的模块中加入了甲的模块,这样一来,模块间的耦合性就大了,如果是在获取信息的时候出错,到底是甲本身写错了,还是说乙在写这一部分的时候粗心大意漏写了什么?这样一来,双方的维护就麻烦了;而后者,乙仅仅拿了甲的接口,模块间的耦合性大大减少,出现了问题之后,一查,就能够知道是甲的问题还是乙的问题了。

所以,为了让代码更加简洁,让模块间的耦合性更加的低,不同模块之间使用回调往往是一个比较好的办法。

## 怎么做?

回调,这个过程,需要用到几个比较重要的知识点:

①函数指针:

指针我们比较熟悉了,例如常见的int *p,p变量就是一个指针,指向的是int类型的数据,同理可得,int (*p_func) (char),这是函数指针,变量p_func是一个指针变量,它指向的是一个返回值为int,参数为char的函数,注意,括号必须使用,否则就是指针函数了(一个返回int类型的指针的函数)。

一般来说,使用typedef定义回调函数类型,后面,就可以直接使用这个类型了,如:

typedef int (*p_func_cb_t) (char);

②注册回调函数:

乙需要用到甲提供的接口,那么,甲的接口函数给到乙的这个过程就叫注册回调函数。注册的方式主要为两种,一种是独立出注册函数,另一种是直接在参数中接收,如下:

**独立注册方式:**

p_func_cb_t g_func_cb;

void register_callback(p_func_cb_t get_func_cb) //这个接口留给甲,甲把乙用到的函数传进来
{
        g_func_cb = get_func_cb; //此时,全局变量已接向甲处了,待会可以直接调用
}

void test()
{
    //omit
    g_func_cb(); //此时,调用了在甲的函数,完成回调
}

在参数中注册:(此方法仅适用于同一个文件下)

test(p_func_cb_t get_func_cb)
{
    //omit
    get_func_cb(); //此时,也已经执行了回调函数
}

现在看下来,是不是有点头绪了呢?

来,再看看完整的代码:

(甲)

#include <stdio.h>
#include "st_enc.h"
   
st_fun_cb g_myfun_cb;  //类型在头文件中

int test_myfun(int x,int y)
{
        printf("I am in test_myfun,x+y = %d !n",x+y);
        return 0;
}

int test_my_minus_fun(int x,int y)
{
        printf("_%s,%d | x - y = %d n",__FILE__, __LINE__, x-y);
        return 0;
}

int g_x,g_y;

int main()
{
        /*a call back function register method which just assign the function pointer with another function name*/
        g_myfun_cb = test_myfun;

        g_x =0; 
        g_y = 0;

        printf("this is going to test 'call back fucntion and its sync or async'...n");
    
        /*assume that st_call is a function without open source,but i have to change something...*/
        /*for example,I'prefer to use minus than add */
        /*the only thing i need to change is the g_myfun_cb, I can change its orientation*/
        st_call(g_myfun_cb,g_x,g_y);

        /*if you register a callback funtion to a global variable in a lib , you can use it when you prefer*/

        printf("test another situation:...n");
        g_myfun_cb(10,20);
        st_call(g_myfun_cb,0,0);



        /*register cb func*/
        register_call_back_func(test_my_minus_fun);
        calculate_cb(10,8);

        return 0;
}

另一个文件(乙):

#include <stdio.h>
#include "st_enc.h"
#include <unistd.h>


int register_call_back_func(st_fun_cb from_up_cb) {
        g_acp_reg_cb = from_up_cb;
        return 0; }

int calculate_cb(int x, int y) {
        st_fun_cb inner_fun_cal_cb = g_acp_reg_cb;
        if(x>0 && y>0)
        {   
                printf("__%s,%d | I am ready to call inner_fun_cal_cb... n",__FILE__,__LINE__,y-x);
                inner_fun_cal_cb(x,y);
        }   
        return 0;

}

int st_call(st_fun_cb myfun, int x, int y) {
        printf("I am in st_call function!n");
        sleep(1);
    
        /*this period, cb funtion may be called by others...*/

        printf("I am going to call the cb function by myself...n");
        myfun(x,y);
        return 0; 
}

头文件:

#ifndef __ST_ENC_H__
#define __ST_ENC_H__

typedef int (*st_fun_cb) (int ,int);

int register_call_back_func(st_fun_cb from_up_cb);
int calculate_cb(int x, int y); 

st_fun_cb g_acp_reg_cb;

int st_call(st_fun_cb myfun,int x,int y); 

#endif

makefile:

all:test_callback

Target = test_callback

Source = st_enc.c call_back_test.c

GCC = gcc 

Include = -I./

Lib = -lpthread 

$(Target):$(Source)
        $(GCC) $(Source) $(Include) $(Lib) -o $(Target)

clean:
        rm -r $(Target)

实验结果:

![在这里插入图片描述](https://img-blog.csdnimg.cn/20200902221820217.png#pic_center)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值