diff --git a/Documentation/pycardium-guide.rst b/Documentation/pycardium-guide.rst index 16ddeb632c5183424bfc120f7025b4854e212bc8..8ff588da326ec7026d381757d2c7e948b0346d03 100644 --- a/Documentation/pycardium-guide.rst +++ b/Documentation/pycardium-guide.rst @@ -164,3 +164,121 @@ QSTRs. Instead all QSTRs needed by modules need to be defined in the header .. _makeqstrdefs.py: https://github.com/micropython/micropython/blob/master/py/makeqstrdefs.py .. _makeqstrdata.py: https://github.com/micropython/micropython/blob/master/py/makeqstrdata.py .. _lib/micropython: https://git.card10.badge.events.ccc.de/card10/firmware/tree/master/lib/micropython + +Functions for MicroPython +------------------------- +As shown in the example above, you can create functions that can be called from +MicroPython code. These functions always have one of the following signatures. +To create a MicroPython object for a function, you need the macro call shown +after each signature. Please place these calls directly after the function +body as shown above. + +.. code-block:: cpp + + /* Function with 0 arguments */ + mp_obj_t mp_example_fun0(void); + static MP_DEFINE_CONST_FUN_OBJ_0(example_fun0_obj, mp_example_fun0); + + /* Function with 1 argument */ + mp_obj_t mp_example_fun1(mp_obj_t arg0_in); + static MP_DEFINE_CONST_FUN_OBJ_1(example_fun1_obj, mp_example_fun0); + + /* Function with 2 arguments */ + mp_obj_t mp_example_fun2(mp_obj_t arg0_in, mp_obj_t arg1_in); + static MP_DEFINE_CONST_FUN_OBJ_2(example_fun2_obj, mp_example_fun0); + + /* Function with 3 arguments */ + mp_obj_t mp_example_fun3(mp_obj_t arg0_in, mp_obj_t arg1_in, mp_obj_t arg2_in); + static MP_DEFINE_CONST_FUN_OBJ_3(example_fun3_obj, mp_example_fun0); + + /* Function with 4 or more arguments */ + mp_obj_t mp_example_fun4(size_t n_args, mp_obj_t *args); + static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(example_fun4_obj, 4, 4, mp_example_fun4); + +For functions with 4 or more arguments, you need to use the +``MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN`` macro and instead of directly accessing +the arguments, you get an array. The macro gets two numbers (they are the same +in the example above): The minimum and maximum number of arguments. + +MicroPython Objects +------------------- +**TL;DR**: Look at |obj.h|_. It contains most functions needed to create, +access, and modify MicroPython objects. + +.. |obj.h| replace:: ``lib/micropython/micropython/py/obj.h`` +.. _obj.h: https://github.com/micropython/micropython/blob/master/py/obj.h + +For C modules to interface with MicroPython, you need to be able to interface +with MicroPython objects. The generic type of an object is ``mp_obj_t``. As +you can see in the example above, this is also what a function gets as +arguments and returns back to MicroPython. You can cast ``mp_obj_t`` to +concrete object types if you made sure it is actually the correct type. + +Booleans +~~~~~~~~ +``True`` and ``False`` are *const* objects, called ``mp_const_true`` and +``mp_const_false`` respectively. A usual equality check can be used: + +.. code-block:: cpp + + #include "py/obj.h" + #include "py/runtime.h" + + if (bool_obj == mp_const_true) { + /* is a boolean true */ + } else if (bool_obj == mp_const_false) { + /* is a boolean false */ + } else { + mp_raise_TypeError("arg 0 is not a boolean"); + } + +Integers +~~~~~~~~ +.. todo:: + + Integers + +Strings +~~~~~~~ +.. todo:: + + Strings + +Lists & Tuples +~~~~~~~~~~~~~~ +While lists and tuples can be accessed using type specific functions, you +should refrain from doing so: Use generic indexing functions instead, as they +also allow types derived from lists or tuples or types with custom indexing +implementations (i.e. duck-typing). + +.. code-block:: cpp + + #include "py/obj.h" + #include "py/runtime.h" + + /* Get the length of a list-like object */ + mp_int_t len = mp_obj_get_int(mp_obj_len(list_obj)); + + /* Get element at a specific index */ + mp_obj_t elem5 = mp_obj_subscr( + list_obj, + MP_OBJ_NEW_SMALL_INT(5), + MP_OBJ_SENTINEL + ); + +To create a list or tuple: + +.. code-block:: cpp + + mp_obj_t values[] = { + MP_OBJ_NEW_SMALL_INT(0xde), + MP_OBJ_NEW_SMALL_INT(0xad), + MP_OBJ_NEW_SMALL_INT(0xbe), + MP_OBJ_NEW_SMALL_INT(0xef), + }; + + /* Create a tuple */ + mp_obj_t tuple = mp_obj_new_tuple(4, values); + + /* Create a list */ + mp_obj_t list = mp_obj_new_list(4, values);