在我們的之前的函數調用中,我們通常是通過定義函數,聲明函數,然後直接在main函數裏面直接使用,這種情況相當於有不管有沒有信號來我們都直接響應,那麼我們遇到有條件的去響應事件時,我們應該怎麼做呢,這時我們就引出了函數的回調:
函數回調的用法三步驟:
[1]定義一個回調函數;
[2]提供函數實現的一方在初始化的時候,將回調函數的函數指針註冊給調用者;
[3]當特定的事件或條件發生的時候,調用者使用函數指針調用回調函數對事件進行處理。
舉例如下:
#include<stdio.h>
//具體函數實現 回調函數的實現
//function.c
PTM_INT32 fhdrv_dsp_tune_wave_port(PTM_INT32 unit,PTM_UINT8 port_num, PTM_UINT16 logic_wave_id, PTM_UINT8 set_type);
PTM_INT32 fhdrv_dsp_get_wave_port(PTM_INT32 unit, PTM_UINT8 port_num,PTM_UINT16 *logic_wave_id, PTM_UINT8 *set_type);
PTM_INT32 fhdrv_dsp_get_modulation_format(PTM_INT32 unit, PTM_UINT8 lane_num, ACX00_MODULATION_FORMAT_T *mode_type);
PTM_INT32 fhdrv_dsp_set_modulation_format(PTM_INT32 unit, PTM_UINT8 lane_num, ACX00_MODULATION_FORMAT_T mode_type);
//提供函數註冊,可供其他任務選擇是否調用,開始默認不使用
//fun.h
typedef struct drv_fun
{
INT32 (* dsp_set_wave_port)(INT32 unit, UINT8 port_num, UINT16 logic_wave_id, UINT8 set_type);
INT32 (* dsp_get_wave_port)(INT32 unit, UINT8 port_num, UINT16 *logic_wave_id, UINT8 *set_type);
INT32 (* dsp_set_modulation_format)(INT32 unit,UINT8 port_num, ACX00_MODULATION_FORMAT_T mode_type);
INT32 (* dsp_get_modulation_format)(INT32 unit,UINT8 port_num, ACX00_MODULATION_FORMAT_T* mode_type);
}DRV_FUN;
extern DRV_FUN g_acxx_drv_func={0};
//reg.c
void reg_fun()
{
g_acxx_drv_func.dsp_set_wave_port = fhdrv_dsp_tune_wave_port;
g_acxx_drv_func.dsp_get_wave_port = fhdrv_dsp_get_wave_port;
g_acxx_drv_func.dsp_set_modulation_format = fhdrv_dsp_set_modulation_format;
g_acxx_drv_func.dsp_get_modulation_format = fhdrv_dsp_get_modulation_format;
}
//在項目初始化的時候選擇是否註冊函數
void init()
{
reg_fun();
}
//main.c
#include"fun.h"
int main()
{
g_acxx_drv_func.dsp_set_wave_port(..) //此時用函數是NULL
init();
//這樣就可以使用回調函數了
//而且註冊之後我們也可以不用,這就是函數回調的精妙之處,我們可以有選擇的去使用自己的函數
g_acxx_drv_func.dsp_set_wave_port(..);
}
註釋:我們先定義一組函數指針,然後將具體的實現函數註冊給這定義的函數指針,然後通過是否註冊來判斷是否調用這一組任務。
補充:函數指針的舉例說明:
#include<stdio.h>
#include<string.h>
void check(char* a,char* b,int(*cmp)(const char*,const char*))
{
if(!(*cmp)(a,b))
{
printf("equal\n");
}
else
{
printf("not equal\n");
}
}
int main()
{
char s1[20] = "123";
char s2[20] = "abc";
int(*p)(const char*,const char*);
p = strcmp;
check(s1,s2,p);
return 0;
}
4,現在我們舉一個加減乘除的簡單實現
(1) fun.h 主要是聲明功能實現函數和函數指針的聲明:
//fun.h
//函數聲明
void plus_fun(int a,int b,int* result);
void muls_fun(int a,int b,int* result);
void mult_fun(int a,int b,int* result);
void except_fun(int a,int b,int* result);
//定義函數指針
typedef struct pointer_fun
{
void (*my_plus)(int a,int b,int* result);
void (*my_muls)(int a,int b,int* result);
void (*my_mult)(int a,int b,int* result);
void (*my_except)(int a,int b,int* result);
}POINTER_FUN;
(2) function.c 函數的具體實現:
void plus_fun(int a,int b,int* result)
{
*result = a + b;
}
void muls_fun(int a,int b,int* result)
{
*result = a - b;
}
void mult_fun(int a,int b,int* result)
{
*result = a * b;
}
void except_fun(int a,int b,int* result)
{
if(b != 0)
{
*result = a / b;
}
}
(3) main.c 只要實現函數指針的調用:
#include<stdio.h>
#include"fun.h"
//全局函數的聲明
POINTER_FUN g_pointer_fun = {0};
//函數指針的註冊
void reg_fun()
{
g_pointer_fun.my_plus = plus_fun;
g_pointer_fun.my_muls = muls_fun;
g_pointer_fun.my_mult = mult_fun;
g_pointer_fun.my_except = except_fun;
}
int main()
{
reg_fun(); //在需要調用的地方加入註冊
int result = 0;
if(g_pointer_fun.my_plus != NULL)
{
g_pointer_fun.my_plus(1,2,&result);
printf("result = %d\n",result);
}
g_pointer_fun.my_muls(6,2,&result);
printf("result = %d\n",result);
g_pointer_fun.my_mult(5,2,&result);
printf("result = %d\n",result);
g_pointer_fun.my_except(12,2,&result);
printf("result = %d\n",result);
return 0;
}
(4)gcc main.c function.c 即可得到結果: