ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

RT-Thread Rust 过程宏(rt_macros)实战指南:no_std 环境下导出主线程、初始化段与 Shell 命令

RT-Thread Rust 过程宏(rt_macros)实战指南:no_std 环境下导出主线程、初始化段与 Shell 命令 操作系统嵌入式物联网嵌入式OSRTOS【免费下载链接】rt-threadRT-Thread is an open source IoT Real-Time Operating System (RTOS). https://rt-thread.github.io/rt-thread/项目地址https://gitcode.com/gh_mirrors/rt/rt-thread点击查看免费下载本篇技术指南以 RT-Thread 仓库中 components/rust/docs/5.rt-macro/README.md 为骨架系统讲解rt_macros过程宏库的设计目标、四个核心宏rt_thread_main!、rt_component_export!、rt_app_export!、msh_cmd_export!的签名约束、链接段机制与完整使用示例并深入其源码实现rt_macros与配套示例工程帮助读者在no_std的嵌入式场景中把 Rust 函数无缝接入 RT-Thread 的启动初始化流程与 msh 命令行体系。背景与目标为什么no_std下需要过程宏导出入口RT-Thread 是开源物联网实时操作系统RTOS其内核与组件由 C 语言编写启动流程依赖约定的链接段link section机制系统复位后按阶段遍历各初始化段并依次调用注册的函数指针。Rust 侧要在这样的环境中工作面临一个基本问题——no_std模式下不存在传统意义上的main函数RT-Thread 无法直接看见Rust 逻辑的入口。rt_macros正是为解决这一问题而设计的 Rust 过程宏库它在编译期把用户编写的普通 Rust 函数翻译为符合 C ABI 的包装入口并生成放入特定链接段的数据条目使 RT-Thread 能在启动期初始化段扫描或命令表扫描阶段发现并调用对应的 Rust 逻辑。宏库入口定义于 components/rust/rt_macros/src/lib.rs四个属性宏分别委托给 components/rust/rt_macros/src/macros/mod.rs 下的main、component、app、cmd四个模块实现。提供的宏与 RT-Thread 声明机制的对应关系rt_macros共提供四个#[proc_macro_attribute]属性宏全部对齐 RT-Thread 的初始化声明与 Shell 命令声明约定。1.rt_thread_main!Rust 主线程入口函数签名fn()无参数、无返回值。约束不支持const、unsafe、async、变参不可使用显式 ABI不可含泛型函数可见性必须为默认非pub。作用导出可由 RT-Thread 识别并调用的主线程入口通常对应main函数。值得说明的是从源码 main.rs 可以看到宏还会解析可选的name属性若未提供name会直接报错 must have attributename。因此该宏实际推荐配合name ...使用用于生成内部符号名如__{name}_main_func。2.rt_component_export!组件初始化入口函数签名fn()约束同主线程宏。可选参数name ...用于生成内部符号名宏要求必填。链接段将函数指针落入.rti_fn.4段供 RT-Thread 组件初始化阶段遍历调用。3.rt_app_export!应用初始化入口函数签名fn()约束同上。可选参数name ...。链接段将函数指针落入.rti_fn.6段供 RT-Thread 应用初始化阶段调用。4.msh_cmd_export!Shell 命令导出函数签名fn(args: vec::IntoIterrt_rust::param::ParamItem)即接收一个参数迭代器。属性参数name必填命令名、desc可选命令描述缺省为No desc。链接段与数据生成命令描述结构体并落入FSymTab段命令名与描述以\0结尾的字节数组形式落入.rodata.name段。调用封装生成extern C包装函数(argc, argv)把argv转换为VecParamItem后交给原始 Rust 命令函数处理。链接段与启动流程初始化与命令扫描机制RT-Thread 通过固定的链接段组织初始化条目与命令表rt_macros生成的条目落入以下四个段段名用途对应宏.rti_fn.4组件初始化入口rt_component_export!.rti_fn.6应用初始化入口rt_app_export!FSymTabShell 命令表msh_cmd_export!.rodata.name命令名 / 描述字符串msh_cmd_export!RT-Thread 在启动或命令表扫描时会遍历这些段对应的条目并完成注册或调用从而将 Rust 编写的逻辑纳入系统。这意味着只要链接脚本保留了这些段RT-Thread BSP 的链接脚本普遍保留FSymTab与.rti_fn.*段Rust 导出的初始化函数和命令就会与 C 侧INIT_COMPONENT_EXPORT、INIT_APP_EXPORT、MSH_CMD_EXPORT声明的条目一样被自动发现。从源码看初始化宏的展开形态以组件导出宏为例component.rs 生成的展开代码包含三个关键部分一个#[no_mangle] pub unsafe extern C fn __{name}_component_func() - i32包装函数内部调用原始 Rust 函数并返回0一个包着函数指针的struct __{name}_component_seg_struct(*const ())并为其实现unsafe impl Sync一个标记了#[link_section .rti_fn.4]的static条目将包装函数地址以*const ()形式放入段中。应用导出宏 app.rs 的展开形态完全一致只是链接段改为.rti_fn.6。这一设计让 Rust 侧初始化函数与 C 侧INIT_COMPONENT_EXPORT/INIT_APP_EXPORT走完全相同的注册通道。从源码看命令宏的展开形态命令导出宏 cmd.rs 生成的展开代码更复杂包含参数解析包装函数#[no_mangle] pub unsafe extern C fn __{name}_main_func(argc: u32, argv: *const *const u8)遍历argv指针数组逐项按\0计算长度通过ParamItem::new(core::slice::from_raw_parts::static, _(...))构造ParamItem收集为VecParamItem后调用原始 Rust 命令函数字符串数据#[link_section .rodata.name]下的[u8; N]静态字节数组分别保存\0结尾的命令名与描述命令描述结构体#[repr(C)] struct __{name}_cmd_seg_struct { name, desc, opt, func }字段布局与 RT-Threadstruct msh_commandmsh命令表项对齐命令表条目#[link_section FSymTab] static其中func指向一个返回i32的extern C包装__wrap_main。其中opt字段固定为core::ptr::null()。命令名与描述通过Literal::byte_string直接生成字节字面量cmd.rs保证\0结尾且内容精确。参数类型ParamItem命令函数接收的参数类型定义在 components/rust/core/src/param.rs#[derive(Debug)] pub struct ParamItem(static [u8]); impl Deref for ParamItem { type Target [u8]; fn deref(self) - Self::Target { return self.0; } } impl ParamItem { pub fn new(raw: static [u8]) - Self { ParamItem(raw) } } pub type Param VecParamItem as IntoIterator::IntoIter;ParamItem封装一段static的字节切片对应 msh 传入的单个命令行参数通过Deref可以直接按[u8]使用Param则是VecParamItem的迭代器别名即命令函数实际收到的参数类型。使用示例四种宏的完整写法以下示例均可在 components/rust/examples 目录下找到对应工程。主线程入口use rt_macros::rt_thread_main; #[rt_thread_main(name main)] fn main() { // 在此编写主线程逻辑 }组件导出use rt_macros::rt_component_export; #[rt_component_export(name rust_component_registry)] fn my_component_init() { // 组件初始化逻辑 }仓库自带的示例工程 examples/component/component_registry/src/lib.rs 展示了真实用法在enable-logfeature 开启时用#[rt_component_export(name rust_component_registry)]导出统一组件注册入口函数体内调用println!与log!、info!、warn!等日志宏feature 未开启时则提供一个空实现的pub extern C fn component_init()保证库仍可链接。应用导出use rt_macros::rt_app_export; #[rt_app_export(name rust_app_example)] fn my_app_init() { // 应用初始化逻辑 }Shell 命令导出use rt_macros::msh_cmd_export; #[msh_cmd_export(name hello, desc Say hello)] fn hello_cmd(args: vec::IntoIterrt_rust::param::ParamItem) { // 命令处理逻辑例如解析 args 并打印输出 }与 C 代码的交互当需要从 C 侧调用导出的 Rust 入口时应在 C 侧声明原型并使用extern C指定调用约定例如extern C void rust_function_name(void);命令导出宏会生成(argc, argv)形式的extern C包装函数__{name}_main_funcRT-Thread 的 msh 命令系统通过FSymTab表中的func字段调用该包装并将命令行参数经argc/argv传入包装函数内部完成argv到VecParamItem的转换再把参数迭代器交给原始 Rust 函数。Rust 侧命令函数因此拿到的是安全、类型化的参数视图而非裸指针。常见问题与诊断编译期报错宏会在函数签名不符合约束时给出明确的错误信息。例如rt_thread_main!/rt_component_export!/rt_app_export!要求fn()见 main.rs 等处的签名检查msh_cmd_export!要求fn(args: vec::IntoIterrt_rust::param::ParamItem)见 cmd.rs。请按上述签名要求调整函数。name属性缺失三个入口类宏与命令宏都要求name属性缺失时宏会直接报错 must have attributename。可见性要求入口函数应保持默认非pub可见性以满足宏的签名约束检查源码中通过f.vis Visibility::Inherited校验。alloc依赖Shell 命令宏内部使用alloc::vec::Vec需确保运行环境提供全局分配器RT-Thread 通常可满足。rt_rust核心库的分配器实现在 components/rust/core/src/allocator.rs。链接段保留若导出条目未被 RT-Thread 发现请确认链接脚本保留了.rti_fn.4、.rti_fn.6、FSymTab、.rodata.name段且未因链接优化如--gc-sections被回收。进一步阅读宏库入口与模块划分components/rust/rt_macros/src/lib.rs、components/rust/rt_macros/src/macros/mod.rs四个宏的独立实现main.rs、component.rs、app.rs、cmd.rs参数类型与运行时支持components/rust/core/src/param.rs、components/rust/core/src/allocator.rs完整示例工程components/rust/examples/applicationthread / mutex / semaphore / queue / param / fs / loadlib、components/rust/examples/component/component_registry、components/rust/examples/modules/example_libRust 支持相关文档components/rust/docs/2.applications/README.md、components/rust/docs/3.components/README.md、components/rust/docs/4.modules/README.md赞分享操作系统嵌入式物联网嵌入式OSRTOS【免费下载链接】rt-threadRT-Thread is an open source IoT Real-Time Operating System (RTOS). https://rt-thread.github.io/rt-thread/项目地址https://gitcode.com/gh_mirrors/rt/rt-thread点击查看免费下载相关推荐RT-Thread Rust 宏库 rt_macros 实战指南no_std 入口导出与 MSH 命令注册RT Thread Rust 宏库 rt_macros 实战指南no_std 入口导出与 MSH 命令注册 rt_macros 是 RT Thread Rus操作系统嵌入式物联网嵌入式OSRTOSRT-Thread 中的 Rust 用户应用开发实战从例程编译到命令导出RT Thread 中的 Rust 用户应用开发实战从例程编译到命令导出 本篇技术指南以 RT Thread 仓库中 components/rust/docs操作系统嵌入式物联网嵌入式OSRTOSpowerline-config 命令完全指南tmux 与 Shell 配置探测、环境初始化的实战解析powerline config 命令完全指南tmux 与 Shell 配置探测、环境初始化的实战解析 powerline config 是 Powerlin开发工具CLI上一篇CANN/Ascend C SIMD浮点转整型下一篇终极虚幻引擎dump工具UEDumper完全指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表