rt_macros 是为 RT-Thread 提供的 Rust 过程宏集合,帮助在 no_std 环境下将 Rust 函数以约定的方式导出为系统入口、初始化段或 Shell 命令,从而与 RT-Thread 的启动与命令机制顺畅对接。
在 no_std 模式下不能直接使用传统的 main 函数。rt_macros 通过过程宏生成符合 C ABI 的包装入口,以及必要的链接段条目,让 RT-Thread 能在启动期或命令扫描阶段发现并调用对应的 Rust 逻辑。
rt_thread_main!:标记 Rust 主线程入口。
fn()(无参数、无返回值)。const、unsafe、async、变参;不可使用显式 ABI;不可含泛型;函数可见性需为默认(非 pub)。rt_component_export!:导出为组件初始化入口。
fn()。name = "..."(用于生成内部符号名称)。.rti_fn.4 段,供组件初始化阶段调用。rt_app_export!:导出为应用初始化入口。
fn()。name = "..."。.rti_fn.6 段,供应用初始化阶段调用。msh_cmd_export!:导出为 RT-Thread Shell 命令。
fn(args: vec::IntoIter<rt_rust::param::ParamItem>)。name(必填,命令名),desc(可选,命令描述)。FSymTab 段。\0 结尾的字节数组形式落入 .rodata.name 段。extern "C" 包装函数 (argc, argv),把 argv 转换为 Vec<ParamItem>,再调用原始 Rust 命令函数。.rti_fn.4.rti_fn.6FSymTab.rodata.nameRT-Thread 在启动或命令表扫描时,会遍历对应段的条目并完成调用或注册,从而将 Rust 编写的逻辑纳入系统。
use rt_macros::rt_thread_main;
#[rt_thread_main]
fn main() {
// 在此编写主线程逻辑
}
use rt_macros::rt_component_export;
#[rt_component_export(name = "rust_component_registry")]
fn my_component_init() {
// 组件初始化逻辑
}
use rt_macros::rt_app_export;
#[rt_app_export(name = "rust_app_example")]
fn my_app_init() {
// 应用初始化逻辑
}
use rt_macros::msh_cmd_export;
#[msh_cmd_export(name = "hello", desc = "Say hello")]
fn hello_cmd(args: vec::IntoIter<rt_rust::param::ParamItem>) {
// 命令处理逻辑,例如解析 args 并打印输出
}
当需要从 C 调用导出的 Rust 入口时,应在 C 侧声明原型并使用 extern "C" 指定调用约定,例如:
extern "C" void rust_function_name(void);
命令导出宏会生成 (argc, argv) 形式的包装函数,RT-Thread 的命令系统会调用该包装函数并将参数传递给原始 Rust 函数。
fn() 或必须为特定的参数形式)。请按上文的签名要求调整。pub),以满足宏的约束。alloc 依赖:Shell 命令宏内部使用 alloc::vec::Vec,需确保运行环境提供分配器(RT-Thread 通常可满足)。