如何在MicroPython中实现C代码对Python函数的调用
问题解答
MicroPython 完全支持C侧代码调用Python层定义的函数,具体实现方案如下:
小提示:你提供的C代码示例存在笔误,调用
foo_Py_Fun时传入的大写I和形参名i不匹配,实现时需要先修正这个问题。
实现步骤
- 依赖头文件引入:C代码中需要先引入MicroPython的核心头文件,获取类型定义和调用API
#include "py/runtime.h" #include "py/obj.h"
- 获取Python函数对象:MicroPython中所有Python对象均为
mp_obj_t类型,全局定义的Python函数可以直接通过名称查找获取引用
mp_obj_t py_fun = mp_load_name(qstr_from_str("foo_Py_Fun"));
如果目标函数定义在自定义Python模块中,需要先导入对应模块再从模块属性中提取函数对象。
- 封装参数并调用函数:使用MicroPython提供的通用调用API
mp_call_function_n_kw执行Python函数,之后将返回值转为C侧可用的类型即可,完整的bar_C_Fun实现如下:
float bar_C_Fun(int i, int j) { // 频繁调用的场景可以把py_fun提取为全局变量缓存,不用每次调用都查找 mp_obj_t py_fun = mp_load_name(qstr_from_str("foo_Py_Fun")); // 转换C类型参数为MicroPython对象 mp_obj_t call_args[2] = {mp_obj_new_int(i), mp_obj_new_int(j)}; // 调用Python函数:参数依次为函数对象、位置参数个数、关键字参数个数、参数数组 mp_obj_t res = mp_call_function_n_kw(py_fun, 2, 0, call_args); // 转换返回值为C的float类型 return mp_obj_get_float(res); }
注意事项
- 必须保证调用
bar_C_Fun前,Python层的foo_Py_Fun已经完成定义,否则会抛出名称不存在的运行时异常 - 如果需要处理Python函数抛出的异常(比如示例中j为0时的除零错误),可以在C层通过
mp_get_exception()接口捕获异常做对应处理,避免程序直接崩溃 - 频繁调用的场景下可以提前缓存
py_fun的全局引用,不需要每次调用都执行名称查找,能大幅提升调用性能
内容的提问来源于stack exchange,提问作者Hadi Moghaddar
相关产品推荐
相关产品推荐

