C语言开发MicroPython模块(添加module)
MicroPython添加模块框架模式相对简单,只需要按照定义好的固定框架就可以添加模块(module)。
一、向固件里面添加module
1.1、编写mymodule.c文件
在ports/esp32文件夹下新建一个文件mymodule.c ,文件内输入如下内容:
#include "stdint.h"
#include "stdio.h"
#include "py/obj.h"
#include "py/runtime.h"STATIC mp_obj_t mp_my_test_function(mp_obj_t myms){uint32_t Myms = mp_obj_get_int(myms);vTaskDelay(Myms / portTICK_PERIOD_MS);return mp_const_none;}STATIC MP_DEFINE_CONST_FUN_OBJ_1(My_mp_my_test_function, mp_my_test_function);STATIC const mp_rom_map_elem_t modnormal_globals_table[] = {{MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_my_test_module)}, {MP_OBJ_NEW_QSTR(MP_QSTR_mytestfunction), MP_ROM_PTR(&My_mp_my_test_function)}, {MP_OBJ_NEW_QSTR(MP_QSTR_test), MP_ROM_PTR(&modnormal_test_type)},};STATIC MP_DEFINE_CONST_DICT(mp_module_modnormal_globals, modnormal_globals_table);
const mp_obj_module_t mp_module_my_test_mod = {.base = {&mp_type_module}, .globals = (mp_obj_dict_t *)&mp_module_modnormal_globals,
};
文件mymodule.c 内创建了一个mp_module_my_test_mod的模块,它包含了一个funtion和一个type,type定义在其他文件内。
1.2、注册module
我们要把我们定义的module注册到micropython中去,这个是在mpconfigport.h文件中修改,找到MICROPY_PORT_BUILTIN_MODULES 定义的地方按照格式添加我们定义的module:
// extra built in modules to add to the list of known ones
extern const struct _mp_obj_module_t esp_module;
extern const struct _mp_obj_module_t esp32_module;
extern const struct _mp_obj_module_t utime_module;
extern const struct _mp_obj_module_t uos_module;
extern const struct _mp_obj_module_t mp_module_usocket;
extern const struct _mp_obj_module_t mp_module_machine;
extern const struct _mp_obj_module_t mp_module_network;
extern const struct _mp_obj_module_t mp_module_onewire;
extern const struct _mp_obj_module_t mp_module_my_test_mod;//声明模块
#define MICROPY_PORT_BUILTIN_MODULES \{ MP_OBJ_NEW_QSTR(MP_QSTR_esp), (mp_obj_t)&esp_module }, \{ MP_OBJ_NEW_QSTR(MP_QSTR_esp32), (mp_obj_t)&esp32_module }, \{ MP_OBJ_NEW_QSTR(MP_QSTR_utime), (mp_obj_t)&utime_module }, \{ MP_OBJ_NEW_QSTR(MP_QSTR_uos), (mp_obj_t)&uos_module }, \{ MP_OBJ_NEW_QSTR(MP_QSTR_usocket), (mp_obj_t)&mp_module_usocket }, \{ MP_OBJ_NEW_QSTR(MP_QSTR_machine), (mp_obj_t)&mp_module_machine }, \{ MP_OBJ_NEW_QSTR(MP_QSTR_network), (mp_obj_t)&mp_module_network }, \{ MP_OBJ_NEW_QSTR(MP_QSTR__onewire), (mp_obj_t)&mp_module_onewire }, \{ MP_OBJ_NEW_QSTR(MP_QSTR_uhashlib), (mp_obj_t)&mp_module_uhashlib }, \{ MP_OBJ_NEW_QSTR(MP_QSTR_my_test_module), (mp_obj_t)&mp_module_my_test_mod }, \
这里就添加两行代码,第一行是应用外部定义的结构体时要先有声明。第二个需要解释一下,MP_QSTR_my_test_module这个名字要改成自定义的,MP_QSTR_这个一定要保留,后面的my_test_module就是在python中显示的module名字。
然后再修改一下Makefile文件,将mymodule.c编译进去就可以了。
二、向固件里面添加module的原理
在文章C语言开发MicroPython模块(模块框架)里面已经介绍了,编译进内核的模块(module)有四种类型,MicroPython将它们组成四个不同的模块集合,并且定义了不同的名字。
2.1、模块集合
以我们编写的和硬件平台密切相关的 module集合mp_builtin_module_map为例,在objmodule.c文件内有
MP_DEFINE_CONST_MAP(mp_builtin_module_map, mp_builtin_module_table);
其中mp_builtin_module_map就是这个被编译进内核的模块集合的名字,mp_builtin_module_table是存储模块的结构体数组。 MP_DEFINE_CONST_MAP的定义在obj.h文件内,内容如下:
#define MP_DEFINE_CONST_MAP(map_name, table_name) \const mp_map_t map_name = { \.all_keys_are_qstrs = 1, \.is_fixed = 1, \.is_ordered = 1, \.used = MP_ARRAY_SIZE(table_name), \.alloc = MP_ARRAY_SIZE(table_name), \.table = (mp_map_elem_t*)(mp_rom_map_elem_t*)table_name, \}
宏定义MP_DEFINE_CONST_MAP就是定义了一个结构体,这个结构体的内容为mp_map_t
// TODO maybe have a truncated mp_map_t for fixed tables, since alloc=used
// put alloc last in the structure, so the truncated version does not need it
// this would save 1 ROM word for all ROM objects that have a locals_dict
// would also need a trucated dict structuretypedef struct _mp_map_t {size_t all_keys_are_qstrs : 1;size_t is_fixed : 1; // a fixed array that can't be modified; must also be orderedsize_t is_ordered : 1; // an ordered arraysize_t used : (8 * sizeof(size_t) - 3);size_t alloc;mp_map_elem_t *table;
} mp_map_t;
MP_ARRAY_SIZE的定义为:
// get the number of elements in a fixed-size array
#define MP_ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
说明结构体的alloc是模块集合的指针合所占的长度,table是一个指针,这个指针指向了mp_builtin_module_table这个结构体数组。在.table = (mp_map_elem_t*)(mp_rom_map_elem_t*)table_name, \
这行代码里面mp_rom_map_elem_t和mp_map_elem_t的定义为:
// Underlying map/hash table implementation (not dict object or map function)typedef struct _mp_map_elem_t {mp_obj_t key;mp_obj_t value;
} mp_map_elem_t;typedef struct _mp_rom_map_elem_t {mp_rom_obj_t key;mp_rom_obj_t value;
} mp_rom_map_elem_t;
而mp_obj_t和mp_rom_obj_t的定义为:
typedef void *mp_obj_t;
typedef const void *mp_const_obj_t;
typedef mp_const_obj_t mp_rom_obj_t;
所以名字为mp_builtin_module_map的这个模块集合在最终包含了一系列的指针,mp_builtin_module_table这个结构体数组内元素。而mp_builtin_module_table这个结构体数组内的元素则是一个一个的模块。
2.2、模块数组
mp_builtin_module_table的定义如下:
/******************************************************************************/
// Global module table and related functionsSTATIC const mp_rom_map_elem_t mp_builtin_module_table[] = {{ MP_ROM_QSTR(MP_QSTR___main__), MP_ROM_PTR(&mp_module___main__) },{ MP_ROM_QSTR(MP_QSTR_builtins), MP_ROM_PTR(&mp_module_builtins) },{ MP_ROM_QSTR(MP_QSTR_micropython), MP_ROM_PTR(&mp_module_micropython) },#if MICROPY_PY_ARRAY{ MP_ROM_QSTR(MP_QSTR_array), MP_ROM_PTR(&mp_module_array) },
#endif
#if MICROPY_PY_IO{ MP_ROM_QSTR(MP_QSTR_uio), MP_ROM_PTR(&mp_module_io) },
#endif
#if MICROPY_PY_COLLECTIONS{ MP_ROM_QSTR(MP_QSTR_ucollections), MP_ROM_PTR(&mp_module_collections) },
#endif
#if MICROPY_PY_STRUCT{ MP_ROM_QSTR(MP_QSTR_ustruct), MP_ROM_PTR(&mp_module_ustruct) },
#endif#if MICROPY_PY_BUILTINS_FLOAT
#if MICROPY_PY_MATH{ MP_ROM_QSTR(MP_QSTR_math), MP_ROM_PTR(&mp_module_math) },
#endif
#if MICROPY_PY_BUILTINS_COMPLEX && MICROPY_PY_CMATH{ MP_ROM_QSTR(MP_QSTR_cmath), MP_ROM_PTR(&mp_module_cmath) },
#endif
#endif
#if MICROPY_PY_SYS{ MP_ROM_QSTR(MP_QSTR_sys), MP_ROM_PTR(&mp_module_sys) },
#endif
#if MICROPY_PY_GC && MICROPY_ENABLE_GC{ MP_ROM_QSTR(MP_QSTR_gc), MP_ROM_PTR(&mp_module_gc) },
#endif
#if MICROPY_PY_THREAD{ MP_ROM_QSTR(MP_QSTR__thread), MP_ROM_PTR(&mp_module_thread) },
#endif// extmod modules#if MICROPY_PY_UERRNO{ MP_ROM_QSTR(MP_QSTR_uerrno), MP_ROM_PTR(&mp_module_uerrno) },
#endif
#if MICROPY_PY_UCTYPES{ MP_ROM_QSTR(MP_QSTR_uctypes), MP_ROM_PTR(&mp_module_uctypes) },
#endif
#if MICROPY_PY_UZLIB{ MP_ROM_QSTR(MP_QSTR_uzlib), MP_ROM_PTR(&mp_module_uzlib) },
#endif
#if MICROPY_PY_UJSON{ MP_ROM_QSTR(MP_QSTR_ujson), MP_ROM_PTR(&mp_module_ujson) },
#endif
#if MICROPY_PY_URE{ MP_ROM_QSTR(MP_QSTR_ure), MP_ROM_PTR(&mp_module_ure) },
#endif
#if MICROPY_PY_UHEAPQ{ MP_ROM_QSTR(MP_QSTR_uheapq), MP_ROM_PTR(&mp_module_uheapq) },
#endif
#if MICROPY_PY_UTIMEQ{ MP_ROM_QSTR(MP_QSTR_utimeq), MP_ROM_PTR(&mp_module_utimeq) },
#endif
#if MICROPY_PY_UHASHLIB{ MP_ROM_QSTR(MP_QSTR_uhashlib), MP_ROM_PTR(&mp_module_uhashlib) },
#endif
#if MICROPY_PY_UCRYPTOLIB{ MP_ROM_QSTR(MP_QSTR_ucryptolib), MP_ROM_PTR(&mp_module_ucryptolib) },
#endif
#if MICROPY_PY_UBINASCII{ MP_ROM_QSTR(MP_QSTR_ubinascii), MP_ROM_PTR(&mp_module_ubinascii) },
#endif
#if MICROPY_PY_URANDOM{ MP_ROM_QSTR(MP_QSTR_urandom), MP_ROM_PTR(&mp_module_urandom) },
#endif
#if MICROPY_PY_USELECT{ MP_ROM_QSTR(MP_QSTR_uselect), MP_ROM_PTR(&mp_module_uselect) },
#endif
#if MICROPY_PY_USSL{ MP_ROM_QSTR(MP_QSTR_ussl), MP_ROM_PTR(&mp_module_ussl) },
#endif
#if MICROPY_PY_LWIP{ MP_ROM_QSTR(MP_QSTR_lwip), MP_ROM_PTR(&mp_module_lwip) },
#endif
#if MICROPY_PY_WEBSOCKET{ MP_ROM_QSTR(MP_QSTR_websocket), MP_ROM_PTR(&mp_module_websocket) },
#endif
#if MICROPY_PY_WEBREPL{ MP_ROM_QSTR(MP_QSTR__webrepl), MP_ROM_PTR(&mp_module_webrepl) },
#endif
#if MICROPY_PY_FRAMEBUF{ MP_ROM_QSTR(MP_QSTR_framebuf), MP_ROM_PTR(&mp_module_framebuf) },
#endif
#if MICROPY_PY_BTREE{ MP_ROM_QSTR(MP_QSTR_btree), MP_ROM_PTR(&mp_module_btree) },
#endif// extra builtin modules as defined by a portMICROPY_PORT_BUILTIN_MODULES
};
结构体mp_rom_map_elem_t的定义如下:
typedef struct _mp_rom_map_elem_t {mp_rom_obj_t key;mp_rom_obj_t value;
} mp_rom_map_elem_t;
说明mp_builtin_module_table这个数组里面每个元素都必须是mp_rom_map_elem_t类型。当增加一个模块时,就往这个数组里面添加一个元素。下面以第一个数组元素进行分析:
2.2.1、MP_ROM_QSTR
{ MP_ROM_QSTR(MP_QSTR___main__), MP_ROM_PTR(&mp_module___main__) },
MP_ROM_QSTR的定义为:
#define MP_ROM_QSTR(q) MP_OBJ_NEW_QSTR(q)
而MP_OBJ_NEW_QSTR的定义为:
#define MP_OBJ_NEW_QSTR(qst) ((mp_obj_t)((((mp_uint_t)(qst)) << 2) | 2))
其中mp_uint_t的定义为
typedef unsigned int mp_uint_t; // must be pointer size
mp_obj_t的定义为
typedef void *mp_obj_t;
所以MP_ROM_QSTR(MP_QSTR___main__)的作用是将将MP_QSTR___main__强制转换为类型int,然后将结果值左移两位,在将二进制结果的值与2进行或操作,再将结果转换为无符号的指针类型。最终就变成了一个为_main__的无符号指针。
2.2.2、MP_ROM_PTR
MP_ROM_PTR的 定义为:
#define MP_ROM_PTR(p) (p)
2.3、MICROPY_PORT_BUILTIN_MODULES
MICROPY_PORT_BUILTIN_MODULES的定义在mpconfigport.h文件内为
#define MICROPY_PORT_BUILTIN_MODULES \{ MP_OBJ_NEW_QSTR(MP_QSTR_esp), (mp_obj_t)&esp_module }, \{ MP_OBJ_NEW_QSTR(MP_QSTR_esp32), (mp_obj_t)&esp32_module }, \{ MP_OBJ_NEW_QSTR(MP_QSTR_utime), (mp_obj_t)&utime_module }, \{ MP_OBJ_NEW_QSTR(MP_QSTR_uos), (mp_obj_t)&uos_module }, \{ MP_OBJ_NEW_QSTR(MP_QSTR_usocket), (mp_obj_t)&mp_module_usocket }, \{ MP_OBJ_NEW_QSTR(MP_QSTR_machine), (mp_obj_t)&mp_module_machine }, \{ MP_OBJ_NEW_QSTR(MP_QSTR_network), (mp_obj_t)&mp_module_network }, \{ MP_OBJ_NEW_QSTR(MP_QSTR__onewire), (mp_obj_t)&mp_module_onewire }, \{ MP_OBJ_NEW_QSTR(MP_QSTR_uhashlib), (mp_obj_t)&mp_module_uhashlib }, \
MP_OBJ_NEW_QSTR的定义与MP_ROM_QSTR相同。
以上就是将module添加进固件的指针指向的原理。
C语言开发MicroPython模块(添加module)相关推荐
- C语言-apache mod(模块开发)-采用apxs开发实战(centos7.2 linux篇)
C语言-apache mod(模块开发)-采用apxs开发实战(centos7.2 linux篇) 名词解释:apxs apxs is a tool for building and installi ...
- python用什么来写模块-使用C语言编写Python模块-引子【转】
为什么要用C语言写Python模块,是Python不够香么?还是觉得头发还茂盛?都不是.因为C语言模块有几个显而易见的好处: 可以使用Python调用C标准库.系统调用等; 假设已经有了一堆C代码实现 ...
- micropython 模块_MicroPython添加Module(一)
前面已经将MicroPython移植到了LPC1788,其中的一些功能已经可以使用.但是片上外设.板载外设还不能访问,需要我们去实现,然后才能在MicroPython中访问.官方文档MicroPyth ...
- axis2开发webservice之编写Axis2模块(Module)
axis2中的模块化开发.能够让开发者自由的加入自己所需的模块.提高开发效率,减少开发的难度. Axis2能够通过模块(Module)进行扩展. Axis2模块至少须要有两个类,这两个类分别实现了Mo ...
- Go语言开发设置代理Goproxy,提高Go安装模块速度
Go语言开发设置代理Goproxy,提高Go安装模块速度 Linux/MacOS 在Linux/MacOS系统上可以执行下列命令: # Enable the go modules feature ex ...
- java创建出现module_Eclipse创建Maven多模块工程Module开发(图文教程)
自己研究了下eclipse用maven多模块工程module开发,跟大家分享一下! 功能模块来分module,跟java的package类似,一般是按照的功能模块分module,比如:sso/cas/ ...
- 微信小程序开发实战3 使用Go语言开发Web服务
3.使用Go语言开发Web服务 微信小程序提供了一系列服务端API用以配合小程序前端来完成相应的功能,以及帮助开发者进行各类数据分析.业务管理和信息查询等操作.例如小程序用户信息的获取就是通过服务端A ...
- 1 Go语言开发环境搭建详细教程+go常见bug合集【Go语言教程】
Go语言开发环境搭建[Win.Linux.Mac] 1 SDK下载 官网地址:golang.org,因为一些原因国内可能无法访问.可以使用下面第二个链接. 国内地址访问:https://golang. ...
- ecmall 开发新模块
要开发新模块,要借鉴原有模块的代码并进行修改. 首先打开目录external/modules 会有一个datacall文件夹,这个文件夹对应的就是一个模块. 复制datacall文件夹,重命名为tes ...
最新文章
- 【mysql的编程专题⑤】自定义函数
- JavaWeb--MVC案例1-------(4)删除
- Golang的协程(goroutine)和同步机制
- mysql drop库_Mysql 删除数据库drop database详细介绍
- 站长如何屏蔽流氓宽带商在你的页面里面强行插入的广告代码
- signal(SIGHUP, SIG_IGN)的含义
- openCV5-getTickCount
- 如何去掉空格 oracle,oracle数据库中如何去除空格
- java毕业设计高校多媒体设备报修管理系统源码+系统+数据库+lw文档+调试运行
- html中怎么隐藏一些符号,html 的一些特殊符号
- H5弹出是否打开微信APP的方式
- 第十三届蓝桥杯大赛软件赛省赛真题
- 网站的广告位投放注意事项
- 凡人修仙传之百炼冥门java_修仙缘:细说我与《凡人修仙传》的过往
- mysql只比较月日的情况
- baidu+app+per+android,超级授权管理 SuperSU v2.82 SR5 for Android
- 云服务平台有哪些?云算力网络哪家强?
- c语言指针与一维数组PPT,C语言第5章指针和一维数组.ppt
- 2022年PMP项目管理考试敏捷知识点(1)
- 美容护理行业的暴利时代即将结束?
热门文章
- Process Hacker(进程管理器) v3.0.2581绿色版便携版
- 【Python-GPU加速】基于Numba的GPU计算加速(一)基本
- 新版本的GPU(2080ti)与NVIDIA驱动(driver 440/cuda 10.2)安装旧版的tensorflow(1.6)
- 连接池_DbUtils
- 让程序不触发 Vista/Win7下应用程序兼容性助手弹出
- 一篇有关主板跳线设置的文章,推荐!!!
- 利用canvas给图片添加水印
- 创业大赛策划承办机构|创成汇
- 四十.DM9000网卡搭建
- 你知道蜻蜓.fm是长在阿里云上的吗?