0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

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

STM32嵌入式开发 来源:STM32嵌入式开发 作者:STM32嵌入式开发 2022-03-14 10:19 次阅读

函数是C语言的核心概念。主调函数(caller)调用被调函数(callee)是一般的调用关系,如果被调函数(callee)参数包含函数指针,函数指针还可以形成多一层的调用关系,形成第三方函数的调用,专业术语称为回调(callback),通过函数指针参数调用的第三方函数称为回调函数。

回调可以让被调函数(这里是指用函数指针做函数参数的函数)的代码更加泛化或抽象,能够简单模拟其它编程语言的委托与反射语法。

1 简单模拟委托

//C语言简单模拟委托//需要用的指针函数。通过用指针函数作为地址接收函数地址,以达到委托其他函数实现某方法的目的。#include typedef void(* fun)(); //typedef 把void(*)()类型重命名为funvoid func(fun); // 被调函数void func_1(); // 回调函数1void 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 "); 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 < (node_t *)&__stop_ss;p++) { p->p(a, b); a+=1;b+=2; }}/*func_1 6 7func_2 10 24 */

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • C语言
    +关注

    关注

    180

    文章

    7604

    浏览量

    136656
  • 函数
    +关注

    关注

    3

    文章

    4327

    浏览量

    62564
  • 编译器
    +关注

    关注

    1

    文章

    1623

    浏览量

    49104

原文标题:C语言使用回调函数模拟委托与反射

文章出处:【微信号:c-stm32,微信公众号:STM32嵌入式开发】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    同样是函数,在CC++中有什么区别

    同样是函数,在 CC++ 中有什么区别? 第一个返回值。 C语言函数可以不写返回值类型,
    的头像 发表于 11-29 10:25 258次阅读

    使用C语言实现函数模

      用C语言能不能实现一个通用的函数,既能完成整数的相加,又能完成浮点数的相加?
    的头像 发表于 11-09 11:38 370次阅读

    C语言中的socket编程基础

    数据 步骤6:关闭socket 创建socket 在C语言中,创建socket需要使用socket()函数。这个函数需要两个参数:域
    的头像 发表于 11-01 16:51 296次阅读

    请问ESP32C3 I2S驱动支持回函数获取数据吗?

    目前I2S驱动只看到i2s_read接口获取数据,但这是polling方式的。是否有注册回函数,当数据到达是调用回函数通知上层app?
    发表于 06-28 06:11

    为什么无法停止使用cy_wcm_connect 的rtos定时器回函数

    。 由于 cy_wcm_connect() 函数的某些原因,计时器无法停止。 取而代之的是调用回函数,由于设备已连接到 Wifi,它将再次尝试停止计时器。 我想知道如何以正确的方式停
    发表于 05-24 06:34

    CAPL脚本使用介绍

    CAPL中也有类似于C语言中的回函数的机制,如检测报文周期和错误帧的函数中就可以使用,当周期超界或者总线出现错误帧就会自动调
    的头像 发表于 04-01 11:23 1896次阅读

    C语言内存泄漏问题原理

    内存泄漏问题只有在使用堆内存的时候才会出现,栈内存不存在内存泄漏问题,因为栈内存会自动分配和释放。C语言代码中堆内存的申请函数是malloc。
    发表于 03-19 11:38 519次阅读
    <b class='flag-5'>C</b><b class='flag-5'>语言</b>内存泄漏问题原理

    函数(callback)是什么?回函数的实现方法

    函数是一种特殊的函数,它作为参数传递给另一个函数,并在被调用函数执行完毕后被调用。回
    发表于 03-12 11:46 2896次阅读

    浅谈C语言中的函数定义

    如果函数要使用参数,则必须声明接受参数值的变量。这些变量称为函数的形式参数。 形式参数就像函数内的其他局部变量,在进入函数时被创建,退出函数
    发表于 03-11 10:09 375次阅读

    函数指针与回函数的应用实例

    通常我们说的指针变量是指向一个整型、字符型或数组等变量,而函数指针是指向函数函数指针可以像一般函数一样,用于调用函数、传递参数。
    的头像 发表于 03-07 11:13 399次阅读
    <b class='flag-5'>函数</b>指针与回<b class='flag-5'>调</b><b class='flag-5'>函数</b>的应用实例

    ​​嵌入式中回函数的实现方法

    函数的命名规范没有固定的标准,但是根据通用惯例和编码规范,回函数的命名应该能够反映函数的作用和功能,让其他开发者能够快速理解并使用。
    发表于 03-04 14:49 708次阅读

    C语言中的可变参数介绍

    C 语言为这种情况提供了一个解决方案,它允许您定义一个函数,能根据具体的需求接受可变数量的参数
    发表于 02-28 14:00 305次阅读
    <b class='flag-5'>C</b><b class='flag-5'>语言</b>中的可变参数介绍

    C语言中的动态内存管理讲解

    本章将讲解 C 中的动态内存管理。C 语言为内存的分配和管理提供了几个函数。这些函数可以在 头文件中找到。
    的头像 发表于 02-23 14:03 388次阅读
    <b class='flag-5'>C</b><b class='flag-5'>语言</b>中的动态内存管理讲解

    c语言,c++,java,python区别

    C语言C++、Java和Python是四种常见的编程语言,各有优点和特点。 C语言
    的头像 发表于 02-05 14:11 2353次阅读

    如何解决C语言中的“访问权限冲突”异常?C语言引发异常原因分析

    如何解决C语言中的“访问权限冲突”异常?C语言引发异常原因分析  在C语言中,访问权限冲突异常通
    的头像 发表于 01-12 16:03 5591次阅读