C语言使用回调函数模拟委托与反射
Posted 嵌入式大杂烩
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C语言使用回调函数模拟委托与反射相关的知识,希望对你有一定的参考价值。
👇 星标「嵌入式大杂烩」,一起进步!👇
来源:头条-小智雅汇
函数是C语言的核心概念。主调函数(caller)调用被调函数(callee)是一般的调用关系,如果被调函数(callee)参数包含函数指针,函数指针还可以形成多一层的调用关系,形成第三方函数的调用,专业术语称为回调(callback),通过函数指针参数调用的第三方函数称为回调函数。
回调可以让被调函数(这里是指用函数指针做函数参数的函数)的代码更加泛化或抽象,能够简单模拟其它编程语言的委托与反射语法。
1、简单模拟委托
//C语言简单模拟委托
//需要用的指针函数。通过用指针函数作为地址接收函数地址,以达到委托其他函数实现某方法的目的。
#include <stdio.h>
typedef void(* fun)(); //typedef 把void(*)()类型重命名为fun
void func(fun); // 被调函数
void func_1(); // 回调函数1
void func_2(); // 回调函数2
int 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\\n");
if (f != NULL)
f();
void func_1()
printf("func_1\\n");
void func_2()
printf("func_2\\n");
/*
func
func_1
func_2
func
func_1
func
func_2
*/
2、简单模拟反射
(1)简单模拟反射
高级语言的反射机制,简单来说就是可以通过字符串型获取对应的类或者函数。下面用C来简单模拟反射:
#include <stdio.h>
#include <string.h>
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 <stdio.h>
#define SEC __attribute__((__section__("ss"), aligned(sizeof(void*))))
void func_1 (int a, int b)
printf("%s %d %d\\n", __func__, __LINE__, a+b);
void func_2 (int a, int b)
printf("%s %d %d\\n", __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位于自定义段ss
SEC 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 < (node_t *)&__stop_ss;p++)
p->p(a, b);
a+=1;b+=2;
/*
func_1 6 7
func_2 10 24
*/
版权声明:本文来源网络,免费传达知识,版权归原作者所有。如涉及作品版权问题,请联系我进行删除。
------------ END ------------
往期推荐:
以上是关于C语言使用回调函数模拟委托与反射的主要内容,如果未能解决你的问题,请参考以下文章
C语言篇 + 指针进阶练习 + qsort模拟实现(回调函数思想) + 指针和数组笔试题
对“xxx”类型的已垃圾回收委托进行了回调。这可能会导致应用程序崩溃损坏和数据丢失。向非托管代码传递委托时,托管应用程序必须让这些委托保持活动状态,直到确信不会再次调用它们。 错误解决一例。(代码片段