C语言使用回调函数模拟委托与反射

函数是c语言的核心概念。主调函数(caller)调用被调函数(callee)是一般的调用关系,如果被调函数(callee)参数包含函数指针,函数指针还可以形成多一层的调用关系,形成第三方函数的调用,专业术语称为回调(callback),通过函数指针参数调用的第三方函数称为回调函数。
回调可以让被调函数(这里是指用函数指针做函数参数的函数)的代码更加泛化或抽象,能够简单模拟其它编程语言的委托与反射语法。
1、简单模拟委托
//c语言简单模拟委托//需要用的指针函数。通过用指针函数作为地址接收函数地址,以达到委托其他函数实现某方法的目的。#include typedef void(* fun)(); //typedef 把void(*)()类型重命名为funvoid func(fun); // 被调函数void func_1(); // 回调函数1void func_2(); // 回调函数2int main() // 主函数用做主调函数{ func(func_1); fun f = func_2; f(); func(func_1); func(func_2); getchar(); return 0;}void func(fun f) //fun f为地址,fun * f为f指向的地址的量或者其他{ printf(func); if (f != null) { f(); }}void func_1(){ printf(func_1);}void func_2(){ printf(func_2);}/*funcfunc_1func_2funcfunc_1funcfunc_2*/  
2、简单模拟反射
(1)简单模拟反射
高级语言的反射机制,简单来说就是可以通过字符串型获取对应的类或者函数。
下面用c来简单模拟反射:
#include #include typedef void (*callback)(void);typedef struct { const char *name; callback fn;}callback_t;void f0();void f1();callback_t callbacks[] = { {cmd0, f0}, {cmd1, f1},};void f0() // 回调函数0{ printf(cmd0);}void f1() // 回调函数1{ printf(cmd1);}void do_callback(const char *name) { size_t i; for (i = 0; i < sizeof(callbacks) / sizeof(callbacks[0]); i++) { if (!strcmp(callbacks[i].name, name)) { callbacks[i].fn(); } }}int main(){ do_callback(cmd1); getchar(); return 0;}  
(2)利用自定义段
gcc支持通过使用 __ attribute __ ((section())),将函数、变量放到指定的数据段中。
也就是说,可以让编译器帮我们完成上例中向数组添加成员的动作。借助此机制,回调函数可以在任意文件声明,不需要修改其他文件。自定义段的起始和结束地址,可以通过变量 __ start_sectionname 和 __ stop_sectionname得到例如通过 __ attribute __ ((section(ss))定义自定义段,其开始地址为 & __ start_ss,结束地址为 & __stop_ss。
// https://www.bejson.com/runcode/c920/#include #define sec __attribute__((__section__(ss), aligned(sizeof(void*))))void func_1 (int a, int b){ printf(%s %d %d, __func__, __line__, a+b); }void func_2 (int a, int b){ printf(%s %d %d, __func__, __line__, a*b); }// 编译器会自动提供__start_ss,__stop_ss标志段ss的起止地址extern size_t __start_ss;extern size_t __stop_ss;typedef struct { void (*p)(int, int);} node_t;// 结构体变量a位于自定义段sssec node_t a = { .p = func_1, };sec node_t b = { .p = func_2, };int main(int argc, char **argv){ int a = 3, b = 4; node_t *p; // 遍历段ss,执行node_t结构中的p指向的函数 for (p = (node_t *)&__start_ss; p p(a, b); a+=1;b+=2; }}/*func_1 6 7func_2 10 24*/  


转型攻坚战 “智能化”成新标签,赋能品牌联想推出Lecoo
首款酷睿移动超能版笔记本电脑已正式发布
气体检测仪的选购思路
优化还是转型? 京东1亿元加码物联网领域
赛特斯已实现了百余个边缘计算设备的试验节点部署
C语言使用回调函数模拟委托与反射
超声波换能器安装
虚拟形象赋予AI助手个性化特征,让人机交互体验耳目一新
DSP28335学习笔记(5):GPIO介绍及使用
详解2013年LED照明方案的发展趋势
模拟芯片设计流程解析
Dodocase VR的制作教程
企业组织使用大数据时需避免的错误
造成系统发生短路的三大原因
电子元件老化——电阻器和运算放大器的老化效应
bourns电位器接线图
55英寸OLED防蓝光创维电视盘点 尽可能避免蓝光对视健康危害非常重要
LED显示屏中的自动亮度控制
迄今最高元宇宙世界观游戏IP——GODS元宇宙
再往前走五十年,机器人的定义有了翻天覆地的变化