函数是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;i< sizeof(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文章
1791浏览量
32111 -
C语言
+关注
关注
180文章
7601浏览量
136251 -
函数
+关注
关注
3文章
4308浏览量
62449
原文标题:C语言使用回调函数模拟委托与反射
文章出处:【微信号:mcu168,微信公众号:硬件攻城狮】欢迎添加关注!文章转载请注明出处。
发布评论请先 登录
相关推荐
评论