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 is be part of the MicroPython repository.

  • User module: A module that is useful for your specific project that you maintain in your own repository or private codebase.

  • Dynamic module: A module that can be deployed and imported 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/: A CPython or MicroPython-specific module that is shared across multiple ports.

  • ports/<port>/: A port-specific module.

Note

This chapter describes modules implemented in py/ or core modules. See Extending MicroPython in C 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, array 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 hypothetical new module subsystem in the file modsubsystem.c:

#include "py/builtin.h"
#include "py/runtime.h"

#if MICROPY_PY_SUBSYSTEM

// info()
STATIC mp_obj_t py_subsystem_info(void) {
    return MP_OBJ_NEW_SMALL_INT(42);
}
MP_DEFINE_CONST_FUN_OBJ_0(subsystem_info_obj, py_subsystem_info);

STATIC const mp_rom_map_elem_t mp_module_subsystem_globals_table[] = {
    { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_subsystem) },
    { MP_ROM_QSTR(MP_QSTR_info), MP_ROM_PTR(&subsystem_info_obj) },
};
STATIC MP_DEFINE_CONST_DICT(mp_module_subsystem_globals, mp_module_subsystem_globals_table);

const mp_obj_module_t mp_module_subsystem = {
    .base = { &mp_type_module },
    .globals = (mp_obj_dict_t *)&mp_module_subsystem_globals,
};

MP_REGISTER_MODULE(MP_QSTR_subsystem, mp_module_subsystem, MICROPY_PY_SUBSYSTEM);

#endif

The implementation includes a definition of all functions related to the module and adds the functions to the module’s global table in mp_module_subsystem_globals_table. It also creates the module object with mp_module_subsystem. The module is then registered with the wider system via the MP_REGISTER_MODULE macro.

After building and running the modified MicroPython, the module should now be importable:

>>> import subsystem
>>> subsystem.info()
42
>>>

Our info() function currently returns just a single number but can be extended to do anything. Similarly, more functions can be added to this new module.