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

    文章

    7633

    浏览量

    142151
  • 函数
    +关注

    关注

    3

    文章

    4384

    浏览量

    65139
  • 编译器
    +关注

    关注

    1

    文章

    1663

    浏览量

    50350

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

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

收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    详解hal_entry入口函数

    当使用RTOS时,程序从main函数开始进行线程调度;当没有使用RTOS时,C语言程序的入口函数main函数调用了hal_entry
    的头像 发表于 07-25 15:34 ?1108次阅读

    C语言中的内联函数与宏

    C编程中,内联函数和宏都用于避免函数调用的开销并编写可复用的逻辑部分,但它们在工作方式和安全性方面存在显著差异。
    的头像 发表于 07-25 15:10 ?1282次阅读
    <b class='flag-5'>C</b><b class='flag-5'>语言</b>中的内联<b class='flag-5'>函数</b>与宏

    大彩讲堂:VisualHMI-LUA教程-on_press回函数使用指南

    一、适合范围本文档适用于VisualHMI平台,Lua脚本语言为V5.3版本,配合工程可以完成大部分的内部逻辑处理。二、概述on_press(state,x,y)触摸回函数,当带触摸的串口屏,点击
    的头像 发表于 07-23 16:32 ?522次阅读
    大彩讲堂:VisualHMI-LUA教程-on_press回<b class='flag-5'>调</b><b class='flag-5'>函数</b>使用指南

    大彩讲堂:VisualHMI-LUA教程-on_run回函数使用指南

    一、适合范围本文档适用于VisualHMI平台,Lua脚本语言为V5.3版本,配合工程可以完成大部分的内部逻辑处理。二、概述on_run(screen)周期回函数,用该回
    的头像 发表于 07-23 15:25 ?531次阅读
    大彩讲堂:VisualHMI-LUA教程-on_run回<b class='flag-5'>调</b><b class='flag-5'>函数</b>使用指南

    深入理解C语言函数—编程中的“积木块”艺术

    在编程的世界里,函数就像建筑中的“积木块”——它们是构建复杂程序的基石。通过灵活组合这些模块,开发者能打造出功能强大且结构清晰的代码。函数之所以成为C语言的核心,正是因为它解决了编程中
    的头像 发表于 06-30 17:26 ?971次阅读
    深入理解<b class='flag-5'>C</b><b class='flag-5'>语言</b>:<b class='flag-5'>函数</b>—编程中的“积木块”艺术

    如何使用自定义设置回函数

    你好,我正在尝试编写自己的自定义设置回函数,并使用 fastEnum=false。 是否有任何代码示例或资料可供我参考? void CyU3PUsbRegisterSetupCallback
    发表于 05-21 06:11

    为什么不需要给回函数传递参数

    函数C语言里面一个重要机制。
    的头像 发表于 04-15 10:11 ?364次阅读

    VirtualLab Fusion应用:具有粗糙表面的回复反射器的反射

    系统设置 当试图将独立于入射方向的光大致反射回同一方向时,通常可以使用回反射器。 这个演示展示了如何在非序列场追迹的帮助下对这种结构进行建模。它还包括通过在表面上应用随机函数来对
    发表于 04-02 08:49

    解锁TSMaster fifo函数:报文读取的高效方法

    前言:TSMaster目前有两种读取报文的模式:回函数模式和fifo模式。fifo函数是TSMaster近期新增的函数,本文将重点介绍fifo模块。关于回
    的头像 发表于 03-14 20:04 ?514次阅读
    解锁TSMaster fifo<b class='flag-5'>函数</b>:报文读取的高效方法

    C语言如何处理函数的返回值

    的那样,直接把 1234 赋值给了变量 ret? 搞懂这个问题不难,只要看下汇编代码就行。 把代码编译一下,只编译不链接,得到的就是C对应的汇编代码。 这块是 test 函数,不用管上面这些代码,如果一行一行去分析,没有汇编基础的话确实会头疼。 看下这行代码,很明显,12
    的头像 发表于 01-16 09:21 ?480次阅读

    EE-128:C语言中的DSP:从C调用汇编类成员函数

    电子发烧友网站提供《EE-128:C语言中的DSP:从C调用汇编类成员函数.pdf》资料免费下载
    发表于 01-07 13:48 ?0次下载
    EE-128:<b class='flag-5'>C</b><b class='flag-5'>语言</b>中的DSP:从<b class='flag-5'>C</b>调用汇编类成员<b class='flag-5'>函数</b>

    C语言笔试题

    来看一个C语言笔试题,应该很少有人能给出正确答案。 #include int f(){ printf("this is f ..."); return 1;}int g(){ printf
    的头像 发表于 12-30 09:48 ?452次阅读

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

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

    使用C语言实现函数模

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

    C语言中的socket编程基础

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