嘉楠科技
直播中

fdvcxhtg

9年用户 1106经验值
擅长:嵌入式技术
私信 关注
[问答]

如何调用C的接口来封装micropyton接口?

microPython的库比较少,无法满足需求,请问调用C的接口来封装micropyton接口如何操作?能否提供详细步骤?
        你好,可以参考micropython官方的教程来添加自定义的模块。

回帖(1)

小镇故事多

2025-6-24 17:59:07

在MicroPython中调用C接口封装自定义模块


要将C语言代码封装为MicroPython模块,需要按照以下步骤操作:


1. 编写C语言功能代码


// example_module.c
#include "py/runtime.h"

// 加法函数(带整数检查)
STATIC mp_obj_t example_add(mp_obj_t a_obj, mp_obj_t b_obj) {
    // 检查参数类型
    if (!mp_obj_is_int(a_obj) || !mp_obj_is_int(b_obj)) {
        mp_raise_TypeError("arguments must be integers");
    }

    long a = mp_obj_get_int(a_obj);
    long b = mp_obj_get_int(b_obj);
    return mp_obj_new_int(a + b);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(example_add_obj, example_add);

// 返回字符串的函数
STATIC mp_obj_t example_get_string(void) {
    return mp_obj_new_str("Hello from C module!", 20);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(example_get_string_obj, example_get_string);

// 模块全局函数表
STATIC const mp_rom_map_elem_t example_module_globals_table[] = {
    { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_example) },
    { MP_ROM_QSTR(MP_QSTR_add), MP_ROM_PTR(&example_add_obj) },
    { MP_ROM_QSTR(MP_QSTR_get_string), MP_ROM_PTR(&example_get_string_obj) },
};
STATIC MP_DEFINE_CONST_DICT(example_module_globals, example_module_globals_table);

// 模块定义结构体
const mp_obj_module_t example_user_module = {
    .base = { &mp_type_module },
    .globals = (mp_obj_dict_t *)&example_module_globals,
};

// 注册模块
MP_REGISTER_MODULE(MP_QSTR_example, example_user_module, MODULE_EXAMPLE_ENABLED);

2. 配置MicroPython编译环境


2.1 添加新模块到工程


.c文件放入MicroPython源代码的合适位置,例如ports/stm32/user_modules/目录。


2.2 修改编译配置


ports/stm32/mpconfigport.h中添加:


// 启用自定义模块
#define MODULE_EXAMPLE_ENABLED (1)

// 声明外部模块
extern const struct _mp_obj_module_t example_user_module;

2.3 修改Makefile


在相应端口的Makefile中添加你的模块源文件:


SRC_USERMOD += user_modules/example_module.c

3. 编译并烧写固件


# 在端口目录中执行(例如 ports/stm32)
make clean
make

使用你的设备特定方法烧写新固件。


4. 在MicroPython中使用模块


import example

# 使用加法函数
result = example.add(10, 20)
print(f"10 + 20 = {result}")  # 输出: 10 + 20 = 30

# 获取字符串
text = example.get_string()
print(text)  # 输出: Hello from C module!

# 错误处理示例
try:
    example.add("str", 20)
except TypeError as e:
    print(f"Caught error: {e}")  # 输出: Caught error: arguments must be integers

深入封装:添加C结构到MicroPython对象


// 添加自定义对象类型示例

typedef struct _example_custom_obj_t {
    mp_obj_base_t base;  // 基础对象
    int value;           // 自定义数据
} example_custom_obj_t;

// 创建新对象
STATIC mp_obj_t example_make_custom(mp_obj_t val_obj) {
    example_custom_obj_t *o = m_new_obj(example_custom_obj_t);
    o->base.type = &example_custom_type;
    o->value = mp_obj_get_int(val_obj);
    return MP_OBJ_FROM_PTR(o);
}

// 成员函数:增加值
STATIC mp_obj_t custom_increase(mp_obj_t self_in) {
    example_custom_obj_t *self = MP_OBJ_TO_PTR(self_in);
    self->value++;
    return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(custom_increase_obj, custom_increase);

// 成员函数:获取值
STATIC mp_obj_t custom_get_value(mp_obj_t self_in) {
    example_custom_obj_t *self = MP_OBJ_TO_PTR(self_in);
    return mp_obj_new_int(self->value);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(custom_get_value_obj, custom_get_value);

// 自定义对象方法表
STATIC const mp_rom_map_elem_t custom_locals_dict_table[] = {
    { MP_ROM_QSTR(MP_QSTR_increase), MP_ROM_PTR(&custom_increase_obj) },
    { MP_ROM_QSTR(MP_QSTR_get_value), MP_ROM_PTR(&custom_get_value_obj) },
};
STATIC MP_DEFINE_CONST_DICT(custom_locals_dict, custom_locals_dict_table);

// 自定义对象类型定义
const mp_obj_type_t example_custom_type = {
    { &mp_type_type },
    .name = MP_QSTR_Custom,
    .locals_dict = (mp_obj_dict_t *)&custom_locals_dict,
};

// 在模块中添加构造函数
STATIC const mp_rom_map_elem_t example_module_globals_table[] = {
    // ... 其他项目 ...
    { MP_ROM_QSTR(MP_QSTR_Custom), MP_ROM_PTR(&example_make_custom) },
    // ... 其他项目 ...
};

错误处理最佳实践



  • 使用mp_raise_TypeError验证参数类型

  • 使用mp_raise_ValueError处理无效值

  • 使用nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, ...)处理系统错误


参考资料



  1. MicroPython官方文档: Adding a new module

  2. MicroPython源码示例: ports/stm32/user_modules

  3. Python/C API转换: MicroPython object API


注意:具体编译步骤可能因目标硬件平台(ESP32, STM32, Raspberry Pi Pico等)而异,请参考对应平台的端口说明。

举报

更多回帖

发帖
×
20
完善资料,
赚取积分