当前位置: 首页 > article >正文

面向对象_昂瑞微_作者观点仅供参考

C 语言面向对象编程实例解析选自 OnMicro OM6626 BLE SDK 中的 DFUDevice Firmware Upgrade模块。适合有一定 C 基础、想理解如何在 C 中实现面向对象的初级工程师。一、先看最终效果调用方完全不关心底层实现在 onmicro_dfu.c 中固件升级的核心逻辑是这样写存储操作的// 获取某个存储后端的接口指针constdfu_nvds_itf_t*flash_itfdfu_nvds_itf[DFU_NVDS_ITF_TYPE_FLASH];// 像调用对象方法一样调用flash_itf-enable();flash_itf-get(addr,len,buf);flash_itf-put(addr,len,buf);flash_itf-del(addr,len);flash_itf-disable();不同之处只是数组索引不同——DFU_NVDS_ITF_TYPE_MBR、DFU_NVDS_ITF_TYPE_DUMMY、DFU_NVDS_ITF_TYPE_FLASH_EXT。同一个.get()调用底层可以是读内部 Flash、读 MBR 分区表、甚至返回全0xFF的假数据。这就是多态。二、第一步定义接口函数指针表文件onmicro_dfu_nvds.h// 这就是 C 语言中的接口——一个全是函数指针的结构体typedefstruct{uint8_t(*enable)(void);// 初始化uint8_t(*get)(uint32_tid,uint32_t*lengthPtr,void*buf);// 读取uint8_t(*put)(uint32_tid,uint32_tlength,void*buf);// 写入uint8_t(*del)(uint32_tid,uint32_tlength);// 擦除/删除uint8_t(*disable)(void);// 反初始化}dfu_nvds_itf_t;对应关系C函数指针表C类dfu_nvds_itf_t抽象基类 / 接口结构体内的 5 个函数指针5 个纯虚函数实现文件里创建的具体实例派生类 虚表为什么每个函数参数里没有this指针因为这个项目里每个实现的后端是全局唯一的只有一个内部 Flash、一个 MBR 分区表不需要区分实例。更完善的写法会把第一个参数设计为void *self。三、第二步实现类提供具体函数填表注册文件onmicro_dfu_nvds.c3.1 Flash 后端的实现// 每个函数对标接口中的一个函数指针staticuint8_tonmicro_dfu_nvds_enable_flash(void){drv_sfs_enable();// 使能内部 Flash 控制器returnONMICRO_DFU_NVDS_ST_SUCCESS;}staticuint8_tonmicro_dfu_nvds_get_flash(uint32_taddr,uint32_t*lengthPtr,void*buf){drv_sfs_read(addr,buf,*lengthPtr);// 调用 Flash 驱动读returnONMICRO_DFU_NVDS_ST_SUCCESS;}staticuint8_tonmicro_dfu_nvds_put_flash(uint32_taddr,uint32_tlength,void*buf){drv_sfs_write(addr,buf,length);// 调用 Flash 驱动写returnONMICRO_DFU_NVDS_ST_SUCCESS;}staticuint8_tonmicro_dfu_nvds_erase_flash(uint32_taddr,uint32_tlength){drv_sfs_erase(addr,length);// 调用 Flash 驱动擦除returnONMICRO_DFU_NVDS_ST_SUCCESS;}staticuint8_tonmicro_dfu_nvds_disable_flash(void){returnONMICRO_DFU_NVDS_ST_SUCCESS;}3.2 MBR分区表后端的实现staticuint8_tonmicro_dfu_nvds_get_mbr(uint32_tid,uint32_t*lengthPtr,void*buf){dfu_image_mbr_info*info(dfu_image_mbr_info*)buf;// 调用 MBR 库读取分区信息if(idsizeof(mbr_types)/sizeof(mbr_types[0])mbr_read_part(mbr_types[id],info-address,info-length,info-crc16)0){returnONMICRO_DFU_NVDS_ST_SUCCESS;}else{returnONMICRO_DFU_NVDS_ST_FAILED;}}// ... 其余 4 个函数同理3.3 Dummy 后端的实现占位 / 测试用staticuint8_tonmicro_dfu_nvds_get_dummy(uint32_tid,uint32_t*lengthPtr,void*buf){memset(buf,0xFF,*lengthPtr);// 全部填 FF模拟空 FlashreturnONMICRO_DFU_NVDS_ST_SUCCESS;}// put/del/enable/disable 全部直接返回成功——这是个空实现3.4 组装把函数指针填入虚表数组constdfu_nvds_itf_tdfu_nvds_itf[]{[DFU_NVDS_ITF_TYPE_MBR]{// 索引 0分区表后端onmicro_dfu_nvds_enable_mbr,onmicro_dfu_nvds_get_mbr,onmicro_dfu_nvds_put_mbr,onmicro_dfu_nvds_del_mbr,onmicro_dfu_nvds_disable_mbr},[DFU_NVDS_ITF_TYPE_FLASH]{// 索引 1内部 Flash 后端onmicro_dfu_nvds_enable_flash,onmicro_dfu_nvds_get_flash,onmicro_dfu_nvds_put_flash,onmicro_dfu_nvds_erase_flash,onmicro_dfu_nvds_disable_flash},// ... CFG、EXT_FLASH 等后端[DFU_NVDS_ITF_TYPE_DUMMY]{// 索引 4空后端onmicro_dfu_nvds_enable_dummy,onmicro_dfu_nvds_get_dummy,onmicro_dfu_nvds_put_dummy,onmicro_dfu_nvds_del_dummy,onmicro_dfu_nvds_disable_dummy},};四、第三步配置层注入依赖文件onmicro_dfu_config.h每个固件镜像的存储操作接口和元信息存储接口是可独立配置的typedefstruct{uint16_ttype;// 镜像类型APP / PATCH / CONFIG ...uint32_tbase_address1;// 基地址 1uint32_tbase_address2;// 基地址 2双区备份用uint32_tmax_length;// 最大长度constchar*describe;// 描述仅调试用constdfu_nvds_itf_t*image_ops_itf;// ← 镜像数据读写的接口constdfu_nvds_itf_t*info_ops_itf;// ← 镜像元信息读写的接口可为空uint16_tinfo_id;}dfu_image_t;constdfu_image_tdfu_image_types[]{{IMAGE_TYPE_APP,0x00044000,0x00044000,0x00040000,Application,dfu_nvds_itf[DFU_NVDS_ITF_TYPE_FLASH],// 镜像存在内部 FlashNULL,// 元信息不需要单独存储0x00},{IMAGE_TYPE_DUMMY,0x00000000,0x00000000,0xFFFFFFFF,Dummy,dfu_nvds_itf[DFU_NVDS_ITF_TYPE_DUMMY],// 镜像用空实现NULL,0x00},};关键在于image_ops_itf和info_ops_itf是dfu_nvds_itf_t类型指针可以指向数组中任意一个实现。新增一种存储后端只需写 5 个static函数在dfu_nvds_itf[]数组中加一项在dfu_image_types[]中把对应的镜像指向它DFU 核心逻辑 onmicro_dfu.c不需要改一行代码。五、执行时的调用流以写入镜像数据为例onmicro_dfu.c 第 281-297 行// 1. 从当前镜像配置中取出操作接口constdfu_nvds_itf_t*write_itfp_env-image_ops_itf;// 2. 统一调用——不需要知道底层是 Flash / MBR / Dummywrite_itf-enable();write_itf-put(write_addr,p_env-cache_recv_len,m_cache);write_itf-disable();对于获取新镜像地址的逻辑第 170-210 行同样使用接口切换if(img-typeIMAGE_TYPE_MBR_MAX){// 系统镜像 → 用 MBR 接口查分区表constdfu_nvds_itf_t*nvds_itfdfu_nvds_itf[DFU_NVDS_ITF_TYPE_MBR];nvds_itf-enable();nvds_itf-get(img-type,len,info);nvds_itf-disable();}elseif(img-typeIMAGE_TYPE_RAW){// 自定义镜像 → 用配置中的 info_ops_itfconstdfu_nvds_itf_t*nvds_itfcmd_img_info-info_ops_itf;// ... same pattern ...}六、总结这个模式的核心思想┌─────────────────────────┐ │ dfu_nvds_itf_t │ ← 接口struct of function pointers │ ┌───────────────────┐ │ │ │ enable() │ │ │ │ get() │ │ │ │ put() │ │ │ │ del() │ │ │ │ disable() │ │ │ └───────────────────┘ │ └───────┬───────┬─────────┘ │ │ ┌─────────────┘ └─────────────┐ ▼ ▼ ┌──────────────────┐ ┌──────────────────┐ │ Flash 实现 │ │ MBR 实现 │ │ drv_sfs_read() │ │ mbr_read_part() │ │ drv_sfs_write() │ │ mbr_write_part() │ └──────────────────┘ └──────────────────┘ │ │ └───────────────┬───────────────────┘ ▼ ┌─────────────────────┐ │ dfu_nvds_itf[] 数组 │ ← 注册表 │ [0] MBR 实现 │ │ [1] Flash 实现 │ │ [2] CFG 实现 │ │ [3] Ext Flash 实现 │ │ [4] Dummy 实现 │ └─────────────────────┘三个关键技巧技巧C 中的实现对应的 OOP 概念1. 结构体里放函数指针typedef struct { uint8_t (*get)(...); } dfu_nvds_itf_t;虚表 / 接口2.static函数隐藏实现所有后端实现函数都声明为static封装private 方法3. 运行时选择实现通过数组索引或指针切换不同表项多态 / 依赖注入为什么嵌入式开发要这么写零额外开销函数指针调用在 ARM 上是BLX Rn和直接函数调用开销几乎一样。没有 C 虚函数的多级间接跳转。无堆分配虚表是const全局数组编译时就确定不占 RAM。可测试可以插入 Dummy 后端返回全0xFF不操作真实硬件即可测试升级流程。易扩展加一种新存储后端比如 SPI NOR Flash只需要新增一个文件写 5 个static函数在数组中注册一行。

相关文章:

面向对象_昂瑞微_作者观点仅供参考

C 语言面向对象编程实例解析 选自 OnMicro OM6626 BLE SDK 中的 DFU(Device Firmware Upgrade)模块。 适合有一定 C 基础、想理解"如何在 C 中实现面向对象"的初级工程师。 一、先看最终效果:调用方完全不关心底层实现 在 onmicro…...

Spread.NET 10-19.1 都可以提供

关于 Spread.NET提供类似 Excel 的电子表格体验。Spread.NET 可帮助您创建电子表格、网格、仪表板和窗体。它包含一个强大的计算引擎,提供 450 多个函数,并支持导入和导出 Excel 电子表格。利用丰富的 .NET 电子表格 API 和强大的计算引擎,您…...

AI智能体记忆系统构建指南:从向量检索到混合搜索的工程实践

1. 项目概述:构建一个能“记住”的智能体最近在折腾AI智能体(Agent)开发的朋友,估计都遇到过同一个头疼的问题:这玩意儿怎么跟金鱼似的,聊两句就忘?你让它帮你整理一份周报,它吭哧吭…...

ToyKind-World:基于Python的ECS架构多智能体模拟框架构建指南

1. 项目概述与核心价值最近在GitHub上看到一个挺有意思的项目,叫“ToyKind-World”。光看这个名字,你可能会觉得有点抽象,是玩具世界?还是某种模拟器?点进去一看,发现它其实是一个用Python构建的、高度可配…...

终极指南:如何让微信网页版在浏览器中重新可用

终极指南:如何让微信网页版在浏览器中重新可用 【免费下载链接】wechat-need-web 让微信网页版可用 / Allow the use of WeChat via webpage access 项目地址: https://gitcode.com/gh_mirrors/we/wechat-need-web 还在为微信网页版无法正常访问而烦恼吗&…...

基于Dify平台快速构建AI对话机器人:从部署到生产级实践

1. 项目概述与核心价值最近在折腾AI应用落地的过程中,我反复被一个问题困扰:如何把一个强大的大语言模型(LLM)能力,快速、低成本地封装成一个能实际解决业务问题的对话机器人?自己从零开始搭框架、写API、处…...

基于RAG与代码专用嵌入模型构建本地智能代码库问答系统

1. 项目概述与核心价值最近在GitHub上看到一个挺有意思的项目,叫“smart-codebase”。光看名字,你可能觉得这又是一个关于代码智能化的工具,但仔细研究其设计和实现思路,你会发现它瞄准的是一个非常具体且高频的痛点:如…...

churrera-cli:Go语言开发的Git仓库批量克隆与自动化管理工具

1. 项目概述:一个为开发者“挤奶油”的命令行工具如果你是一名经常与GitHub、GitLab等代码托管平台打交道的开发者,那么你一定对“克隆仓库”这个动作再熟悉不过了。每天,我们可能都需要从不同的地方拉取代码库,无论是为了学习、复…...

龙虾热降温,我们到底需要什么样的 Agent?

责编 | 《AI 进化论》栏目组出品 | CSDN(ID:CSDNnews)过去几个月,AI Agent 无疑是技术圈最火热的词。我们聊颠覆、聊入口、聊取代……仿佛一夜之间,一个无所不能的“数字员工”就能接管我们的一切工作。热度之下&#…...

AI编程助手规则库实战:从通用到专用的效率跃迁

1. 项目概述:当你的光标有了“规矩”最近在逛GitHub的时候,发现了一个挺有意思的项目,叫“awesome-cursorrules-zh”。光看名字,你可能会有点懵,“Cursor”是那个AI编程工具,“rules”是规则,那…...

考公学习追踪器:用数据驱动备考,打造个人学习仪表盘

1. 项目概述:一个为“考公”学子量身定制的学习追踪器如果你正在准备公务员考试,或者身边有朋友在“考公”,那你一定对那种“学了忘,忘了学”的循环深有体会。行测的题海、申论的素材、时政的热点,每天的学习任务像一座…...

UE5视频插件深度解析:如何实现高效的实时流媒体处理与录制

UE5视频插件深度解析:如何实现高效的实时流媒体处理与录制 【免费下载链接】InVideo 基于UE4实现的rtsp的视频播放插件 项目地址: https://gitcode.com/gh_mirrors/in/InVideo InVideo是一款基于Unreal Engine 5开发的专业级实时视频处理插件,专为…...

从零构建开发者个人网站:技术栈选型、架构设计与自动化部署实践

1. 项目概述:一个开发者个人网站的诞生与演进如果你是一名开发者,大概率会想过拥有一个属于自己的个人网站。它不仅仅是简历的线上版本,更是你的技术名片、思想阵地和项目展厅。今天要聊的这个项目,nelsonlaidev/nelsonlai.dev&am…...

中文文本人性化:从NLP原理到cn-humanizer工程实践

1. 项目概述:为什么我们需要一个中文“人性化”工具?在数字时代,我们与机器生成的文本打交道的机会越来越多。无论是AI助手生成的回复、自动化脚本输出的日志,还是数据清洗后得到的报告,这些文本常常带着一种难以言喻的…...

raylib终极指南:3天从零到一的游戏开发快速入门

raylib终极指南:3天从零到一的游戏开发快速入门 【免费下载链接】raylib A simple and easy-to-use library to enjoy videogames programming 项目地址: https://gitcode.com/GitHub_Trending/ra/raylib raylib是一款专为游戏开发设计的轻量级跨平台框架&am…...

资源管理器约束设计:从核心原理到YARN/K8s实战配置

1. 项目概述:理解资源管理器约束的核心价值在任何一个复杂的计算或资源管理系统中,资源管理器(Resource Manager, 简称RM)都扮演着“交通警察”或“调度中心”的角色。它的核心职责是公平、高效地分配有限的系统资源&a…...

AI编程助手My_CoPaw:从代码补全到智能协作者的架构演进

1. 项目概述:当你的代码有了“猫爪”伙伴最近在GitHub上闲逛,发现一个挺有意思的项目,叫haozhuoyuan/My_CoPaw。光看名字,CoPaw——协作的爪子,是不是立刻联想到“猫爪”(Cat‘s Paw)和“协作”…...

DIY蓝牙游戏手柄:基于Arduino与Cherry MX轴体的全流程制作指南

1. 项目概述与核心思路几年前,我在折腾机械键盘时,看着手边多出来的几颗Cherry MX轴体,突然冒出一个想法:这些清脆、精准的触发单元,除了在键盘上噼里啪啦,能不能变成更直接的操控工具?比如&…...

AI赋能终端:基于LLM的智能命令行助手实现与实战

1. 项目概述:当终端遇见AI,一场效率革命如果你和我一样,每天有超过一半的工作时间是在终端(Terminal)里度过的,那你一定对那种在命令行历史里反复翻找、手动敲击冗长命令、或者为了一个复杂的管道组合而绞尽…...

国产AI模型平台崛起:模力方舟如何破解HuggingFace的本土化困境

在中国AI产业加速落地的今天,模型平台的选择正成为开发者与企业面临的关键决策。全球知名的HuggingFace平台虽然在模型数量上占据优势,但在本土化适配、国产算力支持、工程化落地等方面正面临严峻挑战。与此同时,依托Gitee开源生态成长起来的…...

ModernBERT:用现代训练技术重塑经典BERT,实现性能与效率双提升

1. 项目概述:为什么我们需要一个“现代”的BERT?如果你在过去几年里深度参与过自然语言处理(NLP)项目,那么对BERT这个名字一定不会陌生。作为Transformer架构在预训练领域的里程碑,BERT彻底改变了我们处理文…...

构建多模型备用策略时Taotoken的聚合与路由能力价值

🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 构建多模型备用策略时Taotoken的聚合与路由能力价值 在构建依赖大模型能力的生产应用时,服务的稳定性是核心考量之一。…...

飞凌T507核心板开发实战:开机LOGO、电阻屏校准与双屏异显配置详解

1. 项目概述与核心板简介最近在做一个车载信息娱乐终端的项目,硬件平台选用了飞凌嵌入式的FETT507-C核心板。这块板子基于全志T507这颗四核车规级处理器,Cortex-A53架构,主频1.5GHz,集成了G31 GPU,标配2GB DDR3L内存和…...

开源实践:基于Telnyx与AI构建实时智能通信系统

1. 项目概述:当AI遇上通信,一次开源协作的深度实践最近在GitHub上看到一个挺有意思的项目,叫team-telnyx/ai。光看名字,你可能会觉得这又是一个大模型应用或者AI工具库,但点进去仔细研究,会发现它的内核远不…...

别再卡在‘Setup is running’了!PowerBuilder 9.0保姆级安装避坑指南(附安全模式备用方案)

PowerBuilder 9.0安装全攻略:从卡死困境到高效部署 "Setup is running"这个看似简单的提示框,曾让无数PowerBuilder开发者陷入漫长的等待和反复的重启循环。作为一款承载了二十余年企业级应用开发记忆的经典工具,PowerBuilder 9.0的…...

Axure RP中文界面汉化终极指南:3分钟免费切换,让原型设计更高效

Axure RP中文界面汉化终极指南:3分钟免费切换,让原型设计更高效 【免费下载链接】axure-cn Chinese language file for Axure RP. Axure RP 简体中文语言包。支持 Axure 11、10、9。不定期更新。 项目地址: https://gitcode.com/gh_mirrors/ax/axure-c…...

别再格式化U盘了!Ubuntu 22.04 LTS下永久解决exFAT支持问题的完整配置指南

永久解决Ubuntu 22.04 LTS的exFAT兼容性问题:从原理到实践 当你在Ubuntu系统中插入一个exFAT格式的U盘或移动硬盘时,那个令人沮丧的错误提示可能已经出现过多次:"unknown filesystem type exfat"。这不是偶然现象,而是源…...

TV Bro电视浏览器革命性突破:让Android电视变身智能上网终端

TV Bro电视浏览器革命性突破:让Android电视变身智能上网终端 【免费下载链接】tv-bro Simple web browser for android optimized to use with TV remote 项目地址: https://gitcode.com/gh_mirrors/tv/tv-bro 您是否曾在大屏幕电视前感到手足无措&#xff1…...

开源清理工具OpenClearn:透明可控的数字垃圾管理方案

1. 项目概述:一个开源的“清洁工”如何重塑你的数字生活如果你和我一样,是个在数字世界里摸爬滚打了十几年的老鸟,那你电脑里肯定也有一堆“数字垃圾”。这些垃圾不是指那些过时的文件,而是那些你明明已经删除了,但操作…...

aelf区块链浏览器开发实战:从核心技能到定制化构建

1. 项目概述:一个区块链浏览器背后的技能集如果你在区块链领域,特别是公链开发或生态应用构建中工作过,那么“区块链浏览器”对你来说一定不陌生。它就像是区块链世界的“搜索引擎地图”,让我们能直观地查看链上发生的每一笔交易、…...