MicroPython 嵌入指南:在 C 应用中集成 MicroPython(embed port 实战)
MicroPython 嵌入指南在 C 应用中集成 MicroPythonembed port 实战【免费下载链接】micropythonMicroPython - a lean and efficient Python implementation for microcontrollers and constrained systems项目地址: https://gitcode.com/gh_mirrors/mi/micropython导读本文基于 MicroPython 官方提供的嵌入示例examples/embedding系统讲解如何把 MicroPython 作为一个 C 库嵌入到独立的 C 应用程序中从构建 embed port、生成自包含的micropython_embed源码包到编写宿主 C 程序、初始化运行时、执行 Python 脚本再到脱离仓库树进行“树外out-of-tree”构建。读完本文你将掌握 embed port 的完整工作流、三个核心 C API 的用法与源码级实现原理并能在自己的项目中独立完成嵌入式脚本引擎的集成。一、embed port 是什么MicroPython 官方将“面向特定硬件架构或平台”的实现称为 port如ports/esp32、ports/stm32而 ports/embed 是一个特殊的 port它不面向任何具体硬件而是面向 C 语言本身。它把 MicroPython 运行时编译成一整套可嵌入的.c/.h源文件供宿主项目直接纳入编译从而让现有 C/C 应用获得执行 Python 脚本的能力。从 ports/embed/README.md 可以看到在项目中使用 embed port 主要有三个步骤通过一个mpconfigport.h文件为项目提供 MicroPython 配置用官方提供的embed.mk针对该配置构建 embed port输出一套自包含的 MicroPython 源文件这些文件可以放到仓库之外编译项目这一步要求把第 2 步生成的所有.c文件一并编译。examples/embedding目录正是这三步的最小可运行示范其文件构成如下main.c宿主 C 程序即“被嵌入 MicroPython 的应用”micropython_embed.mk调用 embed port 构建逻辑的 make 片段Makefile示例工程自身的构建脚本可用你自己的构建系统替代mpconfigport.hMicroPython 功能配置头文件README.md本文所依据的官方说明文档。二、构建示例从零生成可运行程序2.1 第一步生成自包含的嵌入源码包在examples/embedding目录下执行$ make -f micropython_embed.mk这一命令会生成micropython_embed目录。它是一份self-contained自包含的 MicroPython 拷贝专门用于嵌入场景目录中的.c文件需要以你的项目所能接受的方式编译进工程示例工程本身使用 make 加Makefile来完成这件事。那么这条命令到底做了什么关键在于 micropython_embed.mk它的内容极短# Set the location of the top of the MicroPython repository. MICROPYTHON_TOP ../.. # Include the main makefile fragment to build the MicroPython component. include $(MICROPYTHON_TOP)/ports/embed/embed.mk它只做两件事定义MICROPYTHON_TOP仓库根目录然后引入 ports/embed/embed.mk。而 embed.mk 中定义了核心目标micropython-embed-package它会把以下内容拷贝进micropython_embed包子目录内容来源说明pypy/*.[ch]核心运行时解释器、编译器、GC、对象模型等extmodextmod/modplatform.h平台模块头shared/runtimeshared/runtime/gchelper.h、gchelper_generic.cGC 辅助代码寄存器与栈扫描genhdrbuild-embed/genhdr/生成头文件moduledefs.h、mpversion.h、qstrdefs.generated.h、root_pointers.hportports/embed/port/*.[ch]嵌入专用 API 实现micropython_embed.h、embed_util.c等构建过程中embed.mk会先通过include $(MICROPYTHON_TOP)/py/mkenv.mk和py/py.mk引入核心环境与 make 定义再以-stdc99 -Wall -Werror等标志准备编译环境并默认关闭 ROM 文本压缩MICROPY_ROM_TEXT_COMPRESSION ? 0可通过变量覆盖。生成的四个头文件属于运行时的“元数据头”它们由仓库工具链如py/makeqstrdata.py、py/makemoduledefs.py派生是包内源码能够编译的前提。2.2 第二步编译示例工程生成micropython_embed目录后直接构建示例可执行程序$ make这一步依据 Makefile 完成。该 Makefile 被刻意保持得极其简单用于演示“只需编译micropython_embed目录下所有.c文件”这一核心要求EMBED_DIR micropython_embed PROG embed CFLAGS -I. CFLAGS -I$(EMBED_DIR) CFLAGS -I$(EMBED_DIR)/port CFLAGS -Wall -Og -fno-common SRC main.c SRC $(wildcard $(EMBED_DIR)/*/*.c) $(wildcard $(EMBED_DIR)/*/*/*.c) OBJ $(SRC:.c.o) $(PROG): $(OBJ) $(CC) -o $ $^注意三个头文件搜索路径当前目录为了找到mpconfigport.h、micropython_embed根目录、以及micropython_embed/port为了找到port/micropython_embed.h。-fno-common可避免嵌入多个编译单元时出现符号合并问题是嵌入式集成中值得保留的防御性选项。官方注释也明确说明这个 Makefile 只是演示实际项目中应替换为你自己的构建系统。2.3 第三步运行$ ./embed程序会依次执行两段 Python 脚本并输出到标准输出例如第一段脚本输出hello world!及一个由生成器表达式构造的列表第二段脚本演示循环、字符串格式化、异常捕获与显式 GC 回收。三、宿主 C 程序剖析main.cmain.c 是整个示例的灵魂完整展示了嵌入 MicroPython 的最小骨架#include port/micropython_embed.h // This is example 1 script, which will be compiled and executed. static const char *example_1 print(hello world!, list(x 1 for x in range(10)), endeol\\n); // This is example 2 script, which will be compiled and executed. static const char *example_2 for i in range(10):\n print(iter {:08}.format(i))\n \n try:\n 1//0\n except Exception as er:\n print(caught exception, repr(er))\n \n import gc\n print(run GC collect)\n gc.collect()\n \n print(finish)\n ; // This array is the MicroPython GC heap. static char heap[8 * 1024]; int main() { int stack_top; mp_embed_init(heap[0], sizeof(heap), stack_top); mp_embed_exec_str(example_1); mp_embed_exec_str(example_2); mp_embed_deinit(); return 0; }3.1 核心流程初始化 → 执行 → 反初始化代码展示了嵌入使用的标准生命周期mp_embed_init传入三个参数——GC 堆起始地址、堆大小、栈顶地址。示例中堆是一块static char heap[8 * 1024]的静态数组8 KB完全由宿主程序提供内存不依赖平台 malloc 策略mp_embed_exec_str把 Python 源码字符串就地编译并执行内部会先编译再运行见下文实现剖析mp_embed_deinit反初始化运行时释放内部状态。关于栈顶参数main.c 的注释给出重要提示stack_top在多数场景下够用但根据运行环境可能有更合适的取栈顶方式例如pthread_get_stackaddr_np、pthread_getattr_np或__builtin_frame_address/__builtin_stack_address。在单线程的裸机/嵌入式场景取局部变量地址即可在多线程环境中则应使用与线程关联的栈信息 API。3.2 嵌入 API 全貌micropython_embed.hport/micropython_embed.h 定义了完整的公开 API一共四个函数void mp_embed_init(void *gc_heap, size_t gc_heap_size, void *stack_top); void mp_embed_deinit(void); // Only available if MICROPY_ENABLE_COMPILER is enabled. void mp_embed_exec_str(const char *src); // Only available if MICROPY_PERSISTENT_CODE_LOAD is enabled. void mp_embed_exec_mpy(const uint8_t *mpy, size_t len);其中mp_embed_exec_str依赖MICROPY_ENABLE_COMPILER示例配置中已开启而mp_embed_exec_mpy用于执行预编译的.mpy字节码需要开启MICROPY_PERSISTENT_CODE_LOAD——这是把脚本预编译后分发、避免目标设备上携带编译器的重要路径。3.3 实现原理embed_util.cport/embed_util.c 给出了上述 API 的底层实现我们可以借此看清“嵌入”背后的真实调用链。初始化mp_embed_initvoid mp_embed_init(void *gc_heap, size_t gc_heap_size, void *stack_top) { mp_stack_set_top(stack_top); gc_init(gc_heap, (uint8_t *)gc_heap gc_heap_size); mp_init(); }依次完成三件事用宿主提供的栈顶设置 MicroPython 的栈指针跟踪用于栈溢出保护与 GC 栈扫描、用宿主提供的堆区间初始化 GCgc_init的第二个参数是堆区间的结束地址、最后mp_init()启动整个运行时。执行字符串脚本mp_embed_exec_strvoid mp_embed_exec_str(const char *src) { nlr_buf_t nlr; if (nlr_push(nlr) 0) { // Compile, parse and execute the given string. mp_lexer_t *lex mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, src, strlen(src), 0); qstr source_name lex-source_name; mp_parse_tree_t parse_tree mp_parse(lex, MP_PARSE_FILE_INPUT); mp_obj_t module_fun mp_compile(parse_tree, source_name, true); mp_call_function_0(module_fun); nlr_pop(); } else { // Uncaught exception: print it out. mp_obj_print_exception(mp_plat_print, (mp_obj_t)nlr.ret_val); } }其执行管线与 MicroPython REPL 高度一致用mp_lexer_new_from_str_len把源码字符串包装为词法器源名记为stdinmp_parse生成解析树mp_compile编译为模块函数对象最后mp_call_function_0调用执行。整个编译执行过程被包在nlr_push/nlr_pop的非本地跳转NLR保护区中一旦 Python 侧抛出异常跳转到else分支并调用mp_obj_print_exception把未捕获异常打印到mp_plat_print——这正是示例脚本里1//0能被try/except正常捕获、且未捕获异常不会弄崩宿主进程的原因。embed_util.c还补全了嵌入场景必需的平台胶水代码gc_collect()当MICROPY_ENABLE_GC开启时通过gc_helper_collect_regs_and_stack完成寄存器与栈的根对象扫描供宿主在合适的时机手动触发完整 GCnlr_jump_fail()NLR 机制在无异常保护区域外失败时的兜底处理__assert_func()仅NDEBUG未定义即调试构建时断言失败的兜底处理。也就是说embed port 不仅交付了解释器还替宿主承担了异常处理、GC 根扫描、断言等底层细节宿主只需提供堆、栈顶和编译环境。四、配置裁剪mpconfigport.h嵌入场景通常对体积敏感因此 embed port 强调通过mpconfigport.h做配置裁剪。示例的 mpconfigport.h 如下// Include common MicroPython embed configuration. #include port/mpconfigport_common.h // Use the minimal starting configuration (disables all optional features). #define MICROPY_CONFIG_ROM_LEVEL (MICROPY_CONFIG_ROM_LEVEL_MINIMUM) // MicroPython configuration. #define MICROPY_ENABLE_COMPILER (1) #define MICROPY_ENABLE_GC (1) #define MICROPY_PY_GC (1) #define MICROPY_PY_SYS (0)要点解读首先包含 port/mpconfigport_common.h获得 embed port 的公共默认配置基线MICROPY_CONFIG_ROM_LEVEL设为MICROPY_CONFIG_ROM_LEVEL_MINIMUM即“最小起始配置”一次性关闭全部可选功能作为从零裁剪的起点随后按需开启MICROPY_ENABLE_COMPILER编译器mp_embed_exec_str的前置条件、MICROPY_ENABLE_GC与MICROPY_PY_GCGC 运行时及其gc模块MICROPY_PY_SYS显式关闭sys模块进一步节省 ROM。这套“先全关、再按需开”的配置方式是控制嵌入后二进制体积的关键手段。需要mp_embed_exec_mpy时只需在MICROPY_PERSISTENT_CODE_LOAD上开启对应功能即可。五、树外Out-of-tree构建把 MicroPython 作为子模块示例默认在 MicroPython 仓库树内即可开箱即用但真实项目中宿主应用通常位于仓库之外。官方 README 明确指出唯一需要改动的地方是把micropython_embed.mk中的MICROPYTHON_TOP指向 MicroPython 仓库的位置。例如# Set the location of the top of the MicroPython repository. MICROPYTHON_TOP /path/to/your/checkout/of/micropython官方还建议了一种典型集成方式把 MicroPython 仓库作为你项目的 git submodule然后在自己的顶层 Makefile 中include $(MICROPYTHON_TOP)/ports/embed/embed.mk复用其micropython-embed-package目标生成micropython_embed包再将其纳入你的构建系统CMake、Meson、手写 Makefile 皆可只要保证所有.c参与编译且头文件搜索路径覆盖micropython_embed与micropython_embed/port。此外embed.mk中PACKAGE_DIR ? micropython_embed可通过变量覆盖从而自定义生成的源码包目录名生成的包由于只含普通.c/.h文件可以自由放置到仓库之外的任何位置甚至复制进宿主工程的源码树。六、从示例到生产嵌入实战要点综合官方 README 与源码实现把 embed port 用于真实项目时建议关注以下几点内存规划GC 堆由宿主静态数组或专用内存区提供示例用 8 KB实际大小需按脚本复杂度与对象分配量评估栈顶参数必须正确传递多线程环境优先使用线程栈 API配置先行先确定需要哪些功能编译器、GC、持久化字节码、sys模块等在mpconfigport.h中显式声明避免携带无用功能膨胀固件脚本执行方式源码字符串用mp_embed_exec_str追求体积与启动速度时用mpy-cross预编译脚本并以mp_embed_exec_mpy加载.mpy数据异常边界mp_embed_exec_str/mp_embed_exec_mpy内部用 NLR 捕获 Python 异常并打印宿主在调用前后应保持自身的 C 异常/错误处理约定构建集成编译所有micropython_embed下的.c头文件搜索路径至少包含micropython_embed与micropython_embed/port并建议保留-fno-common把MICROPYTHON_TOP指向仓库根目录例如 git submodule即可完全脱离仓库树工作。七、总结examples/embedding以最小可运行的形式演示了 embed port 的完整闭环make -f micropython_embed.mk生成自包含源码包 →make编译宿主程序 →./embed运行 Python 脚本。其背后的 ports/embed 提供了一套面向 C 语言而非具体硬件的移植层配合mp_embed_init/mp_embed_exec_str/mp_embed_exec_mpy/mp_embed_deinit四个 API以及“最小配置 按需开启”的mpconfigport.h裁剪哲学让任何 C/C 项目都能以可预期、可裁剪的方式获得脚本执行能力。对读者而言把micropython_embed.mk中的MICROPYTHON_TOP指向自己的 MicroPython 检出目录即可把整套流程平移到自己的工程中。【免费下载链接】micropythonMicroPython - a lean and efficient Python implementation for microcontrollers and constrained systems项目地址: https://gitcode.com/gh_mirrors/mi/micropython创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

如何搭建自己的文件传输服务?一条Docker命令部署transfer.sh完整教程

如何搭建自己的文件传输服务?一条Docker命令部署transfer.sh完整教程

如何搭建自己的文件传输服务?一条Docker命令部署transfer.sh完整教程 【免费下载链接】transfer.sh Easy and fast file sharing from the command-line. 项目地址: https://gitcode.com/gh_mirrors/tr/transfer.sh transfer.sh 是一款用 Go 语言编写的轻量级…

2026/9/21 16:37:35 阅读更多 →
Handsontable 数据绑定实战指南:六大数据结构、数据装载 API 与空值语义全解析

Handsontable 数据绑定实战指南:六大数据结构、数据装载 API 与空值语义全解析

Handsontable 数据绑定实战指南:六大数据结构、数据装载 API 与空值语义全解析 【免费下载链接】handsontable JavaScript Data Grid / Data Table with a Spreadsheet Look & Feel. Works with React, Angular, and Vue. Supported by the Handsontable team ⚡…

2026/9/21 16:36:34 阅读更多 →
python-sdk 客户端开发指南:用 `Client` 与 MCP 服务器交互的完整实战

python-sdk 客户端开发指南:用 `Client` 与 MCP 服务器交互的完整实战

人工智能MCP 服务MCP Clients 【免费下载链接】python-sdk The official Python SDK for Model Context Protocol servers and clients 项目地址: https://gitcode.com/gh_mirrors/pythonsd/python-sdk 点击查看 免费下载 Client 是 python-sdk 提供给 Python 程序…

2026/9/21 16:36:34 阅读更多 →

最新新闻

2026最新绿荫继承者调试指南:3招解决代码复制跑不通难题

2026最新绿荫继承者调试指南:3招解决代码复制跑不通难题

2026最新绿荫继承者调试指南:3招解决代码复制跑不通难题 刚把掘金技术社区热帖里的代码复制下来,双击运行,控制台直接红屏报错?别慌,这不是你笨,也不是代码烂。很多转岗进开发圈的朋友都卡在第一步:看着别人跑通的“绿荫继承者”模式示例,自己环…

2026/9/22 19:04:09 阅读更多 →
如何编写自己的AI编程技能:MiniMax Skills技能开发与贡献完全教程

如何编写自己的AI编程技能:MiniMax Skills技能开发与贡献完全教程

如何编写自己的AI编程技能:MiniMax Skills技能开发与贡献完全教程 【免费下载链接】skills 项目地址: https://gitcode.com/gh_mirrors/skills18/skills MiniMax Skills 是一个面向 AI 编程工具的开发技能库,让 Claude Code、Cursor、Codex 等 A…

2026/9/22 19:04:09 阅读更多 →
悦读纪博客避坑速查手册:3步搞定代码调试难题

悦读纪博客避坑速查手册:3步搞定代码调试难题

悦读纪博客避坑速查手册:3步搞定代码调试难题 复制来的代码跑不通,报错信息满屏飞,你是不是也盯着屏幕发呆,不知道从哪下手?别慌,这种“复制粘贴即崩溃”的尴尬,几乎每个开发者都经历过。这时候,你需要的不是盲目搜索错误代码,而是一份能直接定位问…

2026/9/22 19:04:09 阅读更多 →
皇牌空战性能调优避坑指南:3个实战案例搞定高并发卡顿

皇牌空战性能调优避坑指南:3个实战案例搞定高并发卡顿

皇牌空战性能调优避坑指南:3个实战案例搞定高并发卡顿 刚学完 Python 或 Go 语法,看着文档里的 for 循环和 if 判断觉得挺简单,真到了公司接手项目,一上线就崩。是不是觉得代码逻辑没错,但服务器 CPU 飙红、响应时间从…

2026/9/22 19:04:09 阅读更多 →
5个关键步骤搞定SSD固态硬盘修复源码最佳实践

5个关键步骤搞定SSD固态硬盘修复源码最佳实践

5个关键步骤搞定SSD固态硬盘修复源码最佳实践 复制来的代码跑不通,报错日志像天书,调试半天没头绪?这不仅是新手噩梦,也是资深开发者常踩的坑。在SSD固态硬盘修复领域,很多教程只给结果不给过程,导致你明明照着写,却因环境差异或底层逻辑理解偏…

2026/9/22 19:04:09 阅读更多 →
3个技巧搞定图片缩小,高频面试题里的坑全在这

3个技巧搞定图片缩小,高频面试题里的坑全在这

3个技巧搞定图片缩小,高频面试题里的坑全在这 昨天帮一个刚转行嵌入式的朋友看代码,他对着屏幕抓耳挠腮,说从网上抄的Python图片处理脚本,一跑就报错,改来改去还是不行。这场景太熟悉了,很多开发者都卡在这里:复制来的代码跑不通,日志满屏红字…

2026/9/22 19:03:08 阅读更多 →

日新闻

3台商务办公笔记本实测:手写实现环境配置,告别卡半天

3台商务办公笔记本实测:手写实现环境配置,告别卡半天

3台商务办公笔记本实测:手写实现环境配置,告别卡半天 配置环境就卡半天?别怪机器慢,多半是你没选对工具链。在Java、Go或Python的项目现场, 手写实现…

2026/9/22 0:00:41 阅读更多 →
剑帝加点速查手册:3分钟搞懂核心逻辑

剑帝加点速查手册:3分钟搞懂核心逻辑

剑帝加点速查手册:3分钟搞懂核心逻辑 面试被问原理答不上来,是不是常态?别慌。很多开发者对着 GitHub 开源仓库里的代码发呆,看似简单实则暗藏玄机。今天这份【剑帝加点】速查手册,直接带你拆解核心实现,把面试必考的原理讲透。…

2026/9/22 0:00:41 阅读更多 →
手写实现图片压缩网站核心:搞定WebP转换与质量调优

手写实现图片压缩网站核心:搞定WebP转换与质量调优

手写实现图片压缩网站核心:搞定WebP转换与质量调优 复制来的代码跑不通不知道怎么调?别慌,这种“复制粘贴地狱”在开发圈太常见了。尤其是做 图片压缩网站…

2026/9/22 0:00:41 阅读更多 →

周新闻

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

直接铺开项目本身吧。这几个月我一直在折腾一件事:用Flutter给OpenHarmony做一款游戏集合类的App,说白了就是把若干小游戏塞进一个壳里,用统一入口分发。这个方向本身不算新鲜,真正让我花了不少心思的,是首页那堆游戏卡…

2026/9/22 4:32:41 阅读更多 →
Word表格编号全攻略:从列表编号到题注交叉引用

Word表格编号全攻略:从列表编号到题注交叉引用

写Word文档,最让人头疼的往往是那些“看起来不起眼”的小问题。比如表格编号这事:今天在表后面多加了两个空白行,明天给客户交稿前发现整个章节的编号全部错位,光是挨个改序号就能耗掉大半个下午。我前阵子帮人整理一份上百页的技…

2026/9/22 4:38:57 阅读更多 →
从第一个站到第二个站:独立开发者的静态网站选型与落地实践

从第一个站到第二个站:独立开发者的静态网站选型与落地实践

1. 项目概述1.1 核心需求解析做独立开发者这几年,说实话,第一个网站上线的那天晚上我兴奋得没睡着。但等它跑了半年,流量惨淡、功能臃肿、代码自己都懒得看第二遍之后,我才慢慢琢磨明白一个道理:第一个网站是练手&…

2026/9/22 8:51:04 阅读更多 →

月新闻

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能分类:[AI/大模型]细分主题:AI 增强型 CI/CD 流水线自动化与 GitOps 实践:Agent 工作流、工具调用与任务拆解:从原型到生产的验收清单很多团队在尝试用大…

2026/9/21 15:36:51 阅读更多 →
容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场分类:[工程技术]细分主题:Kubernetes 生产环境运维与排障实战:可复制的项目复盘模板与决策记录大部分团队的事故复盘报告,最后都变成了躺在 Confluence 或钉…

2026/9/21 15:36:51 阅读更多 →
容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步分类:[工程技术]细分主题:Docker 容器化技术与镜像安全管理:核心链路的逐步实现与关键代码取舍面对一个积累了五六年历史包袱的单体架构应用(包含 Web 接口、后台…

2026/9/22 2:43:42 阅读更多 →