函數是C語言的核心概念。主調函數(caller)調用被調函數(callee)是一般的調用關系,如果被調函數(callee)參數包含函數指針,函數指針還可以形成多一層的調用關系,形成第三方函數的調用,專業術語稱為回調(callback),通過函數指針參數調用的第三方函數稱為回調函數。
回調可以讓被調函數(這里是指用函數指針做函數參數的函數)的代碼更加泛化或抽象,能夠簡單模擬其它編程語言的委托與反射語法。
1、簡單模擬委托
//C語言簡單模擬委托
//需要用的指針函數。通過用指針函數作為地址接收函數地址,以達到委托其他函數實現某方法的目的。
#include
typedefvoid(*fun)();//typedef把void(*)()類型重命名為fun
voidfunc(fun);//被調函數
voidfunc_1();//回調函數1
voidfunc_2();//回調函數2
intmain()//主函數用做主調函數
{
func(func_1);
funf=func_2;
f();
func(func_1);
func(func_2);
getchar();
return0;
}
voidfunc(funf)//funf為地址,fun*f為f指向的地址的量或者其他
{
printf("func
");
if(f!=NULL)
{
f();
}
}
voidfunc_1()
{
printf("func_1
");
}
voidfunc_2()
{
printf("func_2
");
}
/*
func
func_1
func_2
func
func_1
func
func_2
*/
2、簡單模擬反射
(1)簡單模擬反射
高級語言的反射機制,簡單來說,就是可以通過字符串型獲取對應的類或者函數。下面,用C來簡單模擬反射:
#include
#include
typedefvoid(*callback)(void);
typedefstruct{
constchar*name;
callbackfn;
}callback_t;
voidf0();
voidf1();
callback_tcallbacks[]={
{"cmd0",f0},
{"cmd1",f1},
};
voidf0()//回調函數0
{
printf("cmd0");
}
voidf1()//回調函數1
{
printf("cmd1");
}
voiddo_callback(constchar*name)
{
size_ti;
for(i=0;isizeof(callbacks)/sizeof(callbacks[0]);i++){
if(!strcmp(callbacks[i].name,name)){
callbacks[i].fn();
}
}
}
intmain()
{
do_callback("cmd1");
getchar();
return0;
}
(2)利用自定義段
gcc支持通過使用 __ attribute __ ((section())),將函數、變量放到指定的數據段中。也就是說,可以讓編譯器幫我們完成上例中向數組添加成員的動作。
借助此機制,回調函數可以在任意文件聲明,不需要修改其他文件。自定義段的起始和結束地址,可以通過變量 __ start_SECTIONNAME 和 __ stop_SECTIONNAME得到例如通過 __ attribute __ ((section("ss"))定義自定義段,其開始地址為 & __ start_ss,結束地址為 & __stop_ss。
//https://www.bejson.com/runcode/c920/
#include
#defineSEC__attribute__((__section__("ss"),aligned(sizeof(void*))))
voidfunc_1(inta,intb)
{
printf("%s%d%d
",__func__,__LINE__,a+b);
}
voidfunc_2(inta,intb)
{
printf("%s%d%d
",__func__,__LINE__,a*b);
}
//編譯器會自動提供__start_ss,__stop_ss標志段ss的起止地址
externsize_t__start_ss;
externsize_t__stop_ss;
typedefstruct{
void(*p)(int,int);
}node_t;
//結構體變量a位于自定義段ss
SECnode_ta={
.p=func_1,
};
SECnode_tb={
.p=func_2,
};
intmain(intargc,char**argv)
{
inta=3,b=4;
node_t*p;
//遍歷段ss,執行node_t結構中的p指向的函數
for(p=(node_t*)&__start_ss;p(node_t*)&__stop_ss;p++){
p->p(a,b);
a+=1;b+=2;
}
}
/*
func_167
func_21024
*/
原文標題:C語言使用回調函數模擬委托與反射
文章出處:【微信公眾號:硬件攻城獅】歡迎添加關注!文章轉載請注明出處。
-
參數
+關注
關注
11文章
1829瀏覽量
32195 -
C語言
+關注
關注
180文章
7604瀏覽量
136694 -
函數
+關注
關注
3文章
4327瀏覽量
62573
原文標題:C語言使用回調函數模擬委托與反射
文章出處:【微信號:mcu168,微信公眾號:硬件攻城獅】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論