emio 是啥?
emio(全称 embedded micro io)是一套专为裸机和 RTOS 环境设计的字符输入/输出库。它把 C++ 标准库里那套庞大、占内存的 I/O 抽象给压缩成了极小的二进制体积(大约只有 fmtlib 的 1/38),同时兼顾 安全(不抛异常,用 result 返回)和 高效(编译期即可完成大多数工作)。一句话:在资源紧张的 MCU 上,你想要的 printf、scanf、format,全都有,而且不需要堆。
它解决了哪些痛点?
|
痛点 |
传统做法 |
emio 的解决方案 |
|
二进制体积大 |
printf
/ |
仅几KB,几乎不占 ROM |
|
运行时异常 |
抛异常导致 MCU 难以捕获 |
使用 |
|
堆内存需求 |
动态分配字符串缓冲 |
支持 |
|
编译期不可用 |
大多数库只能运行时使用 |
高低层 API 均可在 constexpr 环境下工作 |
|
兼容性差 |
只能在 POSIX 环境跑 |
适配裸机、FreeRTOS、Zephyr 等 RTOS |
安装 & 使用
1️⃣ CMake(推荐)
FetchContent_Declare(
emio
GIT_TAG main
GIT_REPOSITORY https://github.com/Viatorus/emio.git
GIT_SHALLOW TRUE
)
FetchContent_MakeAvailable(emio)
2️⃣ 单文件:直接下载 emio.hpp(Quom 生成的单头文件)放进项目 include/ 目录。
3️⃣ Conan:在 conanfile.txt 加入 emio/0.1.0(目前在 Conan Center)。
编译器要求:支持 C++20,已在 GCC 11
13、Clang 1617 上验证。
快速上手示例
// 高层 API
std::string s = emio::format("答案是 {}.", 42);
int ans{};
if (auto r = emio::scan(s, "答案是 {}.", ans); r) {
emio::print("答案是 {}.", ans);
}
// 零堆使用
emio::static_buffer<128> buf{};
emio::format_to(buf, "十六进制 {:#x}.", 42).value();
buf.view(); // -> "十六进制 0x2a."
优缺点一览
|
优点 |
缺点 |
|
超小体积,几乎不占 ROM |
仍在 beta,部分 API 可能变动 |
|
不抛异常,错误可显式处理 |
文档相对薄弱,社区资源少 |
|
支持 compile‑time 格式化 |
只针对字符 I/O,复杂协议需自行封装 |
|
高层易用、低层可控 |
对老旧编译器(不支持 C++20)不兼容 |
|
多平台(裸机、RTOS) |
需要自行管理 |
小贴士
-
• 想在 ISR(中断)里打印,直接使用
emio::writer+static_buffer,省去堆分配。 -
• 若要在编译期生成日志字符串,
constexpr调用emio::format_to完全没有运行时开销。 -
• 记得在每次
result检查后if (!r) { /* 处理错误 */ },否则错误会悄悄被忽略。
总结
如果你在做资源受限的 MCU 项目,苦恼于 printf 把 ROM 吃光、异常处理又不靠谱,emio 正是为你量身定制的“轻量级 I/O”。它把高层的易用性和低层的可控性结合起来,几乎不增加代码体积,又不牺牲安全性。虽然仍在 beta 阶段,但已经足够在实际项目里替代传统 I/O 方案,值得一试。
项目地址:https://github.com/Viatorus/emio