summaryrefslogtreecommitdiffstatshomepage
path: root/docs/develop
diff options
context:
space:
mode:
Diffstat (limited to 'docs/develop')
-rw-r--r--docs/develop/cmodules.rst160
1 files changed, 75 insertions, 85 deletions
diff --git a/docs/develop/cmodules.rst b/docs/develop/cmodules.rst
index 849d0e60a2..2d08df8282 100644
--- a/docs/develop/cmodules.rst
+++ b/docs/develop/cmodules.rst
@@ -49,8 +49,9 @@ A MicroPython user C module is a directory with the following files:
expanded copy of ``$(USERMOD_DIR)`` to ``SRC_USERMOD``, eg
``SRC_USERMOD += $(EXAMPLE_MOD_DIR)/example.c``
- If you have custom ``CFLAGS`` settings or include folders to define, these
- should be added to ``CFLAGS_USERMOD``, or ``CXXFLAGS_USERMOD``.
+ If you have custom compiler options (like ``-I`` to add directories to search
+ for header files), these should be added to ``CFLAGS_USERMOD`` for C code
+ and to ``CXXFLAGS_USERMOD`` for C++ code.
See below for full usage example.
@@ -58,124 +59,113 @@ A MicroPython user C module is a directory with the following files:
Basic example
-------------
-This simple module named ``example`` provides a single function
-``example.add_ints(a, b)`` which adds the two integer args together and returns
-the result.
+This simple module named ``cexample`` provides a single function
+``cexample.add_ints(a, b)`` which adds the two integer args together and returns
+the result. It can be found in the MicroPython source tree and has
+a source file and a Makefile fragment with content as descibed above::
-Directory::
+ micropython/
+ └──examples/
+ └──usercmodule/
+ └──cexample/
+ ├── examplemodule.c
+ └── micropython.mk
- example/
- ├── example.c
- └── micropython.mk
+Refer to the comments in these 2 files for additional explanation.
+Next to the ``cexample`` module there's also ``cppexample`` which
+works in the same way but shows one way of mixing C and C++ code
+in MicroPython.
-``example.c``
-
-.. code-block:: c
-
- // Include required definitions first.
- #include "py/obj.h"
- #include "py/runtime.h"
- #include "py/builtin.h"
-
- // This is the function which will be called from Python as example.add_ints(a, b).
- STATIC mp_obj_t example_add_ints(mp_obj_t a_obj, mp_obj_t b_obj) {
- // Extract the ints from the micropython input objects
- int a = mp_obj_get_int(a_obj);
- int b = mp_obj_get_int(b_obj);
+Compiling the cmodule into MicroPython
+--------------------------------------
- // Calculate the addition and convert to MicroPython object.
- return mp_obj_new_int(a + b);
- }
- // Define a Python reference to the function above
- STATIC MP_DEFINE_CONST_FUN_OBJ_2(example_add_ints_obj, example_add_ints);
+To build such a module, compile MicroPython (see `getting started
+<https://github.com/micropython/micropython/wiki/Getting-Started>`_),
+applying 2 modifications:
- // Define all properties of the example module.
- // Table entries are key/value pairs of the attribute name (a string)
- // and the MicroPython object reference.
- // All identifiers and strings are written as MP_QSTR_xxx and will be
- // optimized to word-sized integers by the build system (interned strings).
- 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_ints), MP_ROM_PTR(&example_add_ints_obj) },
- };
- STATIC MP_DEFINE_CONST_DICT(example_module_globals, example_module_globals_table);
+- an extra ``make`` flag named ``USER_C_MODULES`` set to the directory
+ containing all modules you want included (not to the module itself).
+ For building the example modules which come with MicroPython,
+ set ``USER_C_MODULES`` to the ``examples/usercmodule`` directory.
+ For your own projects it's more convenient to keep custom code out of
+ the main source tree so a typical project directory structure will look
+ like this::
- // Define module object.
- const mp_obj_module_t example_user_cmodule = {
- .base = { &mp_type_module },
- .globals = (mp_obj_dict_t*)&example_module_globals,
- };
+ my_project/
+ ├── modules/
+ │ └──example1/
+ │ ├──example1.c
+ │ └──micropython.mk
+ │ └──example2/
+ │ ├──example2.c
+ │ └──micropython.mk
+ └── micropython/
+ ├──ports/
+ ... ├──stm32/
+ ...
- // Register the module to make it available in Python
- MP_REGISTER_MODULE(MP_QSTR_example, example_user_cmodule, MODULE_EXAMPLE_ENABLED);
+ with ``USER_C_MODULES`` set to the ``my_project/modules`` directory.
-``micropython.mk``
+- all modules found in this directory will be compiled, but only those
+ which are explicitly enabled will be availabe for importing. Enabling a
+ module is done by setting the preprocessor define from its module
+ registration to 1. For example if the source code defines the module with
-.. code-block:: make
+ .. code-block:: c
- EXAMPLE_MOD_DIR := $(USERMOD_DIR)
+ MP_REGISTER_MODULE(MP_QSTR_cexample, example_user_cmodule, MODULE_CEXAMPLE_ENABLED);
- # Add all C files to SRC_USERMOD.
- SRC_USERMOD += $(EXAMPLE_MOD_DIR)/example.c
- # We can add our module folder to include paths if needed
- # This is not actually needed in this example.
- CFLAGS_USERMOD += -I$(EXAMPLE_MOD_DIR)
+ then ``MODULE_CEXAMPLE_ENABLED`` has to be set to 1 to make the module available.
+ This can be done by adding ``CFLAGS_EXTRA=-DMODULE_CEXAMPLE_ENABLED=1`` to
+ the ``make`` command, or editing ``mpconfigport.h`` or ``mpconfigboard.h``
+ to add
-Finally you will need to define ``MODULE_EXAMPLE_ENABLED`` to 1. This
-can be done by adding ``CFLAGS_EXTRA=-DMODULE_EXAMPLE_ENABLED=1`` to
-the ``make`` command, or editing ``mpconfigport.h`` or
-``mpconfigboard.h`` to add
+ .. code-block:: c
-.. code-block:: c
+ #define MODULE_CEXAMPLE_ENABLED (1)
- #define MODULE_EXAMPLE_ENABLED (1)
-Note that the exact method depends on the port as they have different
-structures. If not done correctly it will compile but importing will
-fail to find the module.
+ Note that the exact method depends on the port as they have different
+ structures. If not done correctly it will compile but importing will
+ fail to find the module.
+To sum up, here's how the ``cexample`` module from the ``examples/usercmodule``
+directory can be built for the unix port:
-Compiling the cmodule into MicroPython
---------------------------------------
+.. code-block:: bash
-To build such a module, compile MicroPython (see `getting started
-<https://github.com/micropython/micropython/wiki/Getting-Started>`_) with an
-extra ``make`` flag named ``USER_C_MODULES`` set to the directory containing
-all modules you want included (not to the module itself). For example:
+ cd micropython/ports/unix
+ make USER_C_MODULES=../../examples/usercmodule CFLAGS_EXTRA=-DMODULE_CEXAMPLE_ENABLED=1 all
+The build output will show the modules found::
-Directory::
+ ...
+ Including User C Module from ../../examples/usercmodule/cexample
+ Including User C Module from ../../examples/usercmodule/cppexample
+ ...
- my_project/
- ├── modules/
- │ └──example/
- │ ├──example.c
- │ └──micropython.mk
- └── micropython/
- ├──ports/
- ... ├──stm32/
- ...
-Building for stm32 port:
+Or for your own project with a directory structure as shown above,
+including both modules and building the stm32 port for example:
.. code-block:: bash
cd my_project/micropython/ports/stm32
- make USER_C_MODULES=../../../modules CFLAGS_EXTRA=-DMODULE_EXAMPLE_ENABLED=1 all
+ make USER_C_MODULES=../../../modules \
+ CFLAGS_EXTRA="-DMODULE_EXAMPLE1_ENABLED=1 -DMODULE_EXAMPLE2_ENABLED=1" all
Module usage in MicroPython
---------------------------
-Once built into your copy of MicroPython, the module implemented
-in ``example.c`` above can now be accessed in Python just
-like any other builtin module, eg
+Once built into your copy of MicroPython, the module
+can now be accessed in Python just like any other builtin module, e.g.
.. code-block:: python
- import example
- print(example.add_ints(1, 3))
+ import cexample
+ print(cexample.add_ints(1, 3))
# should display 4