Implementing a Module¶
This chapter details how to implement a core module in MicroPython. MicroPython modules can be one of the following:
- Built-in module: A general module that should be part of the MicroPython repository
- User module: A module that is useful for your specific project (i.e. project-specific functionality that you maintain in your own repository or private codebase).
- Dynamic module: A module that can be deployed at runtime to your device
A module in MicroPython can be implemented in one of the following locations:
- /py: A core library that mirrors core CPython functionality.
- /extmod: Micropython-specific (or optional core CPython) but shared across multiple ports.
- /ports/port: port-specific module.
Note
This chapter describes modules implemented in /py or core modules .
See Porting MicroPython for details on implementing an external module.
For details on port-specific modules, see Porting MicroPython.
Implementing a core module¶
Like CPython, MicroPython has core builtin modules that can be accessed through import statements.
An example is the gc module discussed in Memory Management.
>>> import gc
>>> gc.enable()
>>>
MicroPython has several other builtin standard/core modules like io, uarray etc.
Adding a new core module involves several modifications.
First, create the C file in the py directory. In this example, we are adding a
new module subinterpreters in the file modsubinterpreters.c:
#include "py/builtin.h"
#include "py/gc.h"
#if MICROPY_PY_SUBINTERPRETERS
// list()
STATIC void py_subinterpreters_list(void) {
gc_collect();
}
MP_DEFINE_CONST_FUN_OBJ_0(subinterpreters_list_obj, py_subinterpreters_list);
STATIC const mp_rom_map_elem_t mp_module_subinterpreters_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_subinterpreters) },
{ MP_ROM_QSTR(MP_QSTR_list), MP_ROM_PTR(&subinterpreters_list_obj) },
};
STATIC MP_DEFINE_CONST_DICT(mp_module_subinterpreters_globals, mp_module_subinterpreters_globals_table);
const mp_obj_module_t mp_module_subinterpreters = {
.base = { &mp_type_module },
.globals = (mp_obj_dict_t *)&mp_module_subinterpreters_globals,
};
MP_REGISTER_MODULE(MP_QSTR_subinterpreters, mp_module_subinterpreters, MICROPY_PY_SUBINTERPRETERS);
#endif
The implementation includes a definition of all functions related to the module and adds the functions to the module’s global table. It also registers the module with its table of globals:
const mp_obj_module_t mp_module_subinterpreters = {
.base = { &mp_type_module },
.globals = (mp_obj_dict_t *)&mp_module_subinterpreters_globals,
};
Expose the module for use in Python with:
MP_REGISTER_MODULE(MP_QSTR_subinterpreters, mp_module_subinterpreters, MICROPY_PY_SUBINTERPRETERS);
After the above implementation, expose the module in the builtins header file by
modifying the builtins.h file:
extern const mp_obj_module_t mp_module_subinterpreters;
Then modify objmodule.c with the module details:
#if MICROPY_PY_SUBINTERPRETERS
{ MP_ROM_QSTR(MP_QSTR_subinterpreters), MP_ROM_PTR(&mp_module_subinterpreters) },
#endif
If this was a success, the module should now be importable:
>>> import subinterpreters
>>> subinterpreters.list()
>>>
Our list() function currently returns nothing as it calls gc_collect().