diff --git a/docs/source/usermods_03.rst b/docs/source/usermods_03.rst index f54b0b4..92888c6 100644 --- a/docs/source/usermods_03.rst +++ b/docs/source/usermods_03.rst @@ -9,7 +9,7 @@ as the current working directory. !cd ../../micropython/ports/unix/ .. parsed-literal:: - /home/v923z/sandbox/micropython/v1.11/micropython/ports/unix + /home/v923z/sandbox/micropython/v1.20.0/micropython/ports/unix The micropython codebase itself is set up a rather modular way. Provided you cloned the micropython repository with @@ -25,11 +25,11 @@ see something like this: !ls ../../../micropython/ .. parsed-literal:: - ACKNOWLEDGEMENTS docs lib pic16bit teensy zephyr - bare-arm drivers LICENSE py tests - cc3200 esp8266 logo qemu-arm tools - CODECONVENTIONS.md examples minimal README.md unix - CONTRIBUTING.md extmod mpy-cross stmhal windows + ACKNOWLEDGEMENTS docs lib pic16bit teensy zephyr + bare-arm drivers LICENSE py tests + cc3200 esp8266 logo qemu-arm tools + CODECONVENTIONS.md examples minimal README.md unix + CONTRIBUTING.md extmod mpy-cross stmhal windows Out of all the directoties, at least two are of particular interest. Namely, ``/py/``, where the python interpreter is implemented, and @@ -40,44 +40,16 @@ these two directories, and perusing the relevant files therein. User modules in micropython --------------------------- -Beginning with the 1.10 version of micropython, it became quite simple +Beginning with the 1.20.0 version of micropython, it became quite simple to add a user-defined C module to the firmware. You simply drop two or three files in an arbitrary directory, and pass two compiler flags to ``make`` like so: .. code:: bash - !make USER_C_MODULES=../../../user_modules CFLAGS_EXTRA=-DMODULE_EXAMPLE_ENABLED=1 all + !make USER_C_MODULES=../../../user_modules Here, the ``USER_C_MODULES`` variable is the location (relative to the -location of ``make``) of your files, while ``CFLAGS_EXTRA`` defines the -flag for your particular module. This is relevant, if you have many -modules, but you want to include only some of them. - -Alternatively, you can set the module flags in ``mpconfigport.h`` (to be -found in the port’s root folder, for which you are compiling) as - -.. code:: make - - #define MODULE_SIMPLEFUNCTION_ENABLED (1) - #define MODULE_SIMPLECLASS_ENABLED (1) - #define MODULE_SPECIALCLASS_ENABLED (1) - #define MODULE_KEYWORDFUNCTION_ENABLED (1) - #define MODULE_CONSUMEITERABLE_ENABLED (1) - #define MODULE_VECTOR_ENABLED (1) - #define MODULE_RETURNITERABLE_ENABLED (1) - #define MODULE_PROFILING_ENABLED (1) - #define MODULE_MAKEITERABLE_ENABLED (1) - #define MODULE_SUBSCRIPTITERABLE_ENABLED (1) - #define MODULE_SLICEITERABLE_ENABLED (1) - #define MODULE_VARARG_ENABLED (1) - #define MODULE_STRINGARG_ENABLED (1) - -and then call ``make`` without the ``CFLAGS_EXTRA`` flag: - -.. code:: bash - - !make USER_C_MODULES=../../../user_modules all -This separation of the user code from the micropython code base is +location of ``make``) of your files. This separation of the user code from the micropython code base is definitely a convenience, because it is much easier to keep track of changes, and also because you can’t possibly screw up micropython itself: you can also go back to a working piece of firmware by dropping diff --git a/docs/source/usermods_04.rst b/docs/source/usermods_04.rst index 82b386c..a144048 100644 --- a/docs/source/usermods_04.rst +++ b/docs/source/usermods_04.rst @@ -100,6 +100,21 @@ called on objects with this new type, i.e., will just work. We return to this question later. +An alternative way to check the type of a variable is to use the +``mp_obj_get_type_str`` and use ``strcmp`` to compare the result with. +``strcmp`` is a C function that compares two strings, and returns 0, if +they are equal. So, if we want to check, whether ``some_variable`` is a +integer, we could write: + +.. code:: c + + if (strcmp(mp_obj_get_type_str(some_variable), "int") == 0) { + // do something + } + +This is not the most elegant way to do it, but it is useful, if you +don't know the type of the variable at compile time. + python constants ---------------- diff --git a/docs/source/usermods_05.rst b/docs/source/usermods_05.rst index d174b20..16c2614 100644 --- a/docs/source/usermods_05.rst +++ b/docs/source/usermods_05.rst @@ -39,7 +39,7 @@ https://github.com/v923z/micropython-usermod/tree/master/snippets/simplefunction .globals = (mp_obj_dict_t*)&simplefunction_module_globals, }; - MP_REGISTER_MODULE(MP_QSTR_simplefunction, simplefunction_user_cmodule, MODULE_SIMPLEFUNCTION_ENABLED); + MP_REGISTER_MODULE(MP_QSTR_simplefunction, simplefunction_user_cmodule); Header files ------------ @@ -160,26 +160,12 @@ module with .. code:: c - MP_REGISTER_MODULE(MP_QSTR_simplefunction, simplefunction_user_cmodule, MODULE_SIMPLEFUNCTION_ENABLED); + MP_REGISTER_MODULE(MP_QSTR_simplefunction, simplefunction_user_cmodule); -This last line is particularly useful, because by setting the -``MODULE_SIMPLEFUNCTION_ENABLED`` variable in ``mpconfigport.h``, you -can selectively exclude modules from the linking, i.e., if in -``mpconfigport.h``, which should be in the root directory of the port -you want to compile for, +This is the function that is called by the interpreter, when the module +is imported. It takes two arguments, the name of the module, and the +module’s globals table, which we have just defined. -.. code:: c - - #define MODULE_SIMPLEFUNCTION_ENABLED (1) - -then ``simplefunction`` will be included in the firmware, while with - -.. code:: c - - #define MODULE_SIMPLEFUNCTION_ENABLED (0) - -the module will be dropped, even though the source is in your modules -folder. (N.B.: the module will still be compiled, but not linked.) Compiling our module -------------------- @@ -196,30 +182,22 @@ https://github.com/v923z/micropython-usermod/tree/master/snippets/simplefunction USERMODULES_DIR := $(USERMOD_DIR) # Add all C files to SRC_USERMOD. - SRC_USERMOD += $(USERMODULES_DIR)/simplefunction.c + SRC_USERMOD_C += $(USERMODULES_DIR)/simplefunction.c CFLAGS_USERMOD += -I$(USERMODULES_DIR) -If ``mpconfigport.h`` is augmented with -.. code:: make - - #define MODULE_SIMPLEFUNCTION_ENABLED (1) you should be able to compile the module above by calling .. code:: bash !make clean - !make USER_C_MODULES=../../../usermod/snippets all + !make USER_C_MODULES=../../../usermod/snippets/simplefunction As mentioned earlier, if you do not want to touch anything in the micropython code base, you can simply pass the definition to make as - -.. code:: bash - - !make clean - !make USER_C_MODULES=../../../usermod/snippets CFLAGS_EXTRA=-DMODULE_SIMPLEFUNCTION_ENABLED=1 all -You will also note that we ran ``make clean`` before the compilation. -This is always good practice, when you are developing your own modules. +shown above. You will also note that we ran ``make clean`` before the +compilation. This is always good practice, when you are developing +your own modules. We can then test the module as diff --git a/docs/source/usermods_06.rst b/docs/source/usermods_06.rst index 105cd7d..37d3508 100644 --- a/docs/source/usermods_06.rst +++ b/docs/source/usermods_06.rst @@ -134,7 +134,7 @@ https://github.com/v923z/micropython-usermod/tree/master/snippets/constants/cons .globals = (mp_obj_dict_t*)&constants_module_globals, }; - MP_REGISTER_MODULE(MP_QSTR_constants, constants_user_cmodule, MODULE_CONSTANTS_ENABLED); + MP_REGISTER_MODULE(MP_QSTR_constants, constants_user_cmodule); https://github.com/v923z/micropython-usermod/tree/master/snippets/constants/micropython.mk @@ -144,13 +144,13 @@ https://github.com/v923z/micropython-usermod/tree/master/snippets/constants/micr USERMODULES_DIR := $(USERMOD_DIR) # Add all C files to SRC_USERMOD. - SRC_USERMOD += $(USERMODULES_DIR)/constants.c + SRC_USERMOD_C += $(USERMODULES_DIR)/constants.c CFLAGS_USERMOD += -I$(USERMODULES_DIR) .. code:: bash !make clean - !make USER_C_MODULES=../../../usermod/snippets CFLAGS_EXTRA=-DMODULE_CONSTANTS_ENABLED=1 all + !make USER_C_MODULES=../../../usermod/snippets/constants One comment before trying out what we have just implemented: the module is definitely pathological. If all you need is a set of constants organised in some way, then you should write it in python. There is diff --git a/docs/source/usermods_07.rst b/docs/source/usermods_07.rst index 8d492b0..ed5cf19 100644 --- a/docs/source/usermods_07.rst +++ b/docs/source/usermods_07.rst @@ -61,7 +61,7 @@ https://github.com/v923z/micropython-usermod/tree/master/snippets/sillyerrors/si .globals = (mp_obj_dict_t*)&sillyerrors_module_globals, }; - MP_REGISTER_MODULE(MP_QSTR_sillyerrors, sillyerrors_user_cmodule, MODULE_SILLYERRORS_ENABLED); + MP_REGISTER_MODULE(MP_QSTR_sillyerrors, sillyerrors_user_cmodule); Now, not all exceptions are created equal. Some are more exceptional than the others: ``ValueError``, ``TypeError``, ``OSError``, and @@ -124,13 +124,13 @@ https://github.com/v923z/micropython-usermod/tree/master/snippets/sillyerrors/mi USERMODULES_DIR := $(USERMOD_DIR) # Add all C files to SRC_USERMOD. - SRC_USERMOD += $(USERMODULES_DIR)/sillyerrors.c + SRC_USERMOD_C += $(USERMODULES_DIR)/sillyerrors.c CFLAGS_USERMOD += -I$(USERMODULES_DIR) .. code:: bash !make clean - !make USER_C_MODULES=../../../usermod/snippets CFLAGS_EXTRA=-DMODULE_SILLYERRORS_ENABLED=1 all + !make USER_C_MODULES=../../../usermod/snippets/sillyerrors .. code :: %%micropython diff --git a/docs/source/usermods_08.rst b/docs/source/usermods_08.rst index 8af5c26..70a7d1b 100644 --- a/docs/source/usermods_08.rst +++ b/docs/source/usermods_08.rst @@ -119,7 +119,7 @@ https://github.com/v923z/micropython-usermod/tree/master/snippets/vararg/vararg. .globals = (mp_obj_dict_t*)&vararg_module_globals, }; - MP_REGISTER_MODULE(MP_QSTR_vararg, vararg_user_cmodule, MODULE_VARARG_ENABLED); + MP_REGISTER_MODULE(MP_QSTR_vararg, vararg_user_cmodule); https://github.com/v923z/micropython-usermod/tree/master/snippets/vararg/micropython.mk @@ -129,13 +129,13 @@ https://github.com/v923z/micropython-usermod/tree/master/snippets/vararg/micropy USERMODULES_DIR := $(USERMOD_DIR) # Add all C files to SRC_USERMOD. - SRC_USERMOD += $(USERMODULES_DIR)/vararg.c + SRC_USERMOD_C += $(USERMODULES_DIR)/vararg.c CFLAGS_USERMOD += -I$(USERMODULES_DIR) .. code:: bash !make clean - !make USER_C_MODULES=../../../usermod/snippets CFLAGS_EXTRA=-DMODULE_VARARG_ENABLED=1 all + !make USER_C_MODULES=../../../usermod/snippets/vararg .. code :: %%micropython @@ -228,7 +228,7 @@ https://github.com/v923z/micropython-usermod/tree/master/snippets/stringarg/stri .globals = (mp_obj_dict_t*)&stringarg_module_globals, }; - MP_REGISTER_MODULE(MP_QSTR_stringarg, stringarg_user_cmodule, MODULE_STRINGARG_ENABLED); + MP_REGISTER_MODULE(MP_QSTR_stringarg, stringarg_user_cmodule); The macro defined in ``objstr.h`` takes three arguments, out of which only the first one is actually defined. The other two are defined in the @@ -271,13 +271,13 @@ https://github.com/v923z/micropython-usermod/tree/master/snippets/stringarg/micr USERMODULES_DIR := $(USERMOD_DIR) # Add all C files to SRC_USERMOD. - SRC_USERMOD += $(USERMODULES_DIR)/stringarg.c + SRC_USERMOD_C += $(USERMODULES_DIR)/stringarg.c CFLAGS_USERMOD += -I$(USERMODULES_DIR) .. code:: bash !make clean - !make USER_C_MODULES=../../../usermod/snippets CFLAGS_EXTRA=-DMODULE_STRINGARG_ENABLED=1 all + !make USER_C_MODULES=../../../usermod/snippets/stringarg .. code :: %%micropython @@ -380,7 +380,7 @@ https://github.com/v923z/micropython-usermod/tree/master/snippets/keywordfunctio .globals = (mp_obj_dict_t*)&keywordfunction_module_globals, }; - MP_REGISTER_MODULE(MP_QSTR_keywordfunction, keywordfunction_user_cmodule, MODULE_KEYWORDFUNCTION_ENABLED); + MP_REGISTER_MODULE(MP_QSTR_keywordfunction, keywordfunction_user_cmodule); One side effect of a function with keyword arguments is that we do not have to care about the arguments in the C implementation: the argument @@ -432,13 +432,13 @@ https://github.com/v923z/micropython-usermod/tree/master/snippets/keywordfunctio USERMODULES_DIR := $(USERMOD_DIR) # Add all C files to SRC_USERMOD. - SRC_USERMOD += $(USERMODULES_DIR)/keywordfunction.c + SRC_USERMOD_C += $(USERMODULES_DIR)/keywordfunction.c CFLAGS_USERMOD += -I$(USERMODULES_DIR) .. code:: bash !make clean - !make USER_C_MODULES=../../../usermod/snippets CFLAGS_EXTRA=-DMODULE_KEYWORDFUNCTION_ENABLED=1 all + !make USER_C_MODULES=../../../usermod/snippets/keywordfunction .. code :: %%micropython @@ -542,7 +542,7 @@ https://github.com/v923z/micropython-usermod/tree/master/snippets/arbitrarykeywo .globals = (mp_obj_dict_t*)&arbitrarykeyword_module_globals, }; - MP_REGISTER_MODULE(MP_QSTR_arbitrarykeyword, arbitrarykeyword_user_cmodule, MODULE_ARBITRARYKEYWORD_ENABLED); + MP_REGISTER_MODULE(MP_QSTR_arbitrarykeyword, arbitrarykeyword_user_cmodule); Before compiling the code, let us think a bit about what is going on here. The first argument, ``a``, is straightforward: that is a @@ -606,13 +606,13 @@ https://github.com/v923z/micropython-usermod/tree/master/snippets/arbitrarykeywo USERMODULES_DIR := $(USERMOD_DIR) # Add all C files to SRC_USERMOD. - SRC_USERMOD += $(USERMODULES_DIR)/arbitrarykeyword.c + SRC_USERMOD_C += $(USERMODULES_DIR)/arbitrarykeyword.c CFLAGS_USERMOD += -I$(USERMODULES_DIR) .. code:: bash !make clean - !make USER_C_MODULES=../../../usermod/snippets CFLAGS_EXTRA=-DMODULE_ARBITRARYKEYWORD_ENABLED=1 all + !make USER_C_MODULES=../../../usermod/snippets/arbitrarykeyword .. code :: %%micropython diff --git a/docs/source/usermods_09.rst b/docs/source/usermods_09.rst index 996cc00..34f76b3 100644 --- a/docs/source/usermods_09.rst +++ b/docs/source/usermods_09.rst @@ -10,25 +10,32 @@ and a local dictionary. A typical class structure would look like .. code:: c + const mp_obj_type_t simpleclass_type; + STATIC const mp_rom_map_elem_t simpleclass_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_method1), MP_ROM_PTR(&simpleclass_method1_obj) }, { MP_ROM_QSTR(MP_QSTR_method2), MP_ROM_PTR(&simpleclass_method2_obj) }, ... } - const mp_obj_type_t simpleclass_type = { - { &mp_type_type }, - .name = MP_QSTR_simpleclass, - .print = simpleclass_print, - .make_new = simpleclass_make_new, - .locals_dict = (mp_obj_dict_t*)&simpleclass_locals_dict, - }; + MP_DEFINE_CONST_OBJ_TYPE( + simpleclass_type, + MP_QSTR_simpleclass, + MP_TYPE_FLAG_NONE, + print, simpleclass_print, + make_new, simpleclass_make_new, + locals_dict, &simpleclass_locals_dict + ); -The locals dictionary, ``.locals_dict``, contains all user-facing -methods and constants of the class, while the ``simpleclass_type`` -structure’s ``name`` member is what our class is going to be called. -``.print`` is roughly the equivalent of ``__str__``, and ``.make_new`` -is the C name for ``__init__``. + +The ``MP_DEFINE_CONST_OBJ_TYPE`` macro defines a structure called +``simpleclass_type``, which is of type ``mp_obj_type_t``. The structure +contains a pointer to the type of the object, ``&mp_type_type``, the +name of the class, ``MP_QSTR_simpleclass``, the flags, which are set to +``MP_TYPE_FLAG_NONE``, the printout and initialisation functions, +``print`` and ``make_new`` which are roughly the equivalent of ``__str__`` +and ``__init__``, and the local dictionary, ``locals_dict`` that contains +all user-facing methods and constants of the class. In order to see how this all works, we are going to implement a very simple class, which holds two integer variables, and has a method that @@ -132,13 +139,14 @@ https://github.com/v923z/micropython-usermod/tree/master/snippets/simpleclass/si STATIC MP_DEFINE_CONST_DICT(myclass_locals_dict, myclass_locals_dict_table); - const mp_obj_type_t simpleclass_myclass_type = { - { &mp_type_type }, - .name = MP_QSTR_simpleclass, - .print = myclass_print, - .make_new = myclass_make_new, - .locals_dict = (mp_obj_dict_t*)&myclass_locals_dict, - }; + MP_DEFINE_CONST_OBJ_TYPE( + simpleclass_myclass_type, + MP_QSTR_simpleclass, + MP_TYPE_FLAG_NONE, + print, myclass_print, + make_new, myclass_make_new, + locals_dict, &myclass_locals_dict + ); // Module functions STATIC mp_obj_t simpleclass_add(const mp_obj_t o_in) { @@ -164,7 +172,7 @@ https://github.com/v923z/micropython-usermod/tree/master/snippets/simpleclass/si .globals = (mp_obj_dict_t*)&mp_module_simpleclass_globals, }; - MP_REGISTER_MODULE(MP_QSTR_simpleclass, simpleclass_user_cmodule, MODULE_SIMPLECLASS_ENABLED); + MP_REGISTER_MODULE(MP_QSTR_simpleclass, simpleclass_user_cmodule); One more thing to note: the functions that are pointed to in ``simpleclass_myclass_type`` are not registered with the macro @@ -183,10 +191,10 @@ so, again, there is no need to turn our function into a function object. Printing class properties ------------------------- -In ``my_print``, instead of the standard the C function ``printf``, we +In ``myclass_print``, instead of the standard the C function ``printf``, we made use of ``mp_print_str``, and ``mp_obj_print_helper``, which are options in this case. Both take ``print`` as their first argument. The -value of ``print`` is supplied by the ``.print`` method of the class +value of ``print`` is supplied by the ``print`` method of the class itself. The second argument is a string (in the case of ``mp_print_str``), or a ``micropython`` object (for ``mp_obj_print_helper``). In addition, ``mp_obj_print_helper`` takes a @@ -205,13 +213,13 @@ https://github.com/v923z/micropython-usermod/tree/master/snippets/simpleclass/mi USERMODULES_DIR := $(USERMOD_DIR) # Add all C files to SRC_USERMOD. - SRC_USERMOD += $(USERMODULES_DIR)/simpleclass.c + SRC_USERMOD_C += $(USERMODULES_DIR)/simpleclass.c CFLAGS_USERMOD += -I$(USERMODULES_DIR) .. code:: bash !make clean - !make USER_C_MODULES=../../../usermod/snippets CFLAGS_EXTRA=-DMODULE_SIMPLECLASS_ENABLED=1 all + !make USER_C_MODULES=../../../usermod/snippets/simpleclass .. code :: %%micropython @@ -370,12 +378,12 @@ function, ``myclass_make_new``, immediately after the argument checking. When implementing the operators, we have to keep a couple of things in mind. First, the ``specialclass_myclass_type`` has to be extended with -the two methods, ``.unary_op``, and ``.binary_op``, where ``.unary_op`` -is equal to the function that handles the unary operation -(``specialclass_unary_op`` in the example below), and ``.binary_op`` is -equal to the function that deals with binary operations -(``specialclass_binary_op`` below). These two functions have the -signatures +the two pairs, ``unary_op``, and ``binary_op``, and their callback +functions. Where ``unary_op``'s callback is the function that handles +the unary operation (``specialclass_unary_op`` in the example below), +and ``binary_op``'s callback is the function that deals with binary +operations (``specialclass_binary_op`` below). These two functions have +the signatures .. code:: c @@ -390,7 +398,7 @@ and respectively, and we have to inspect the value of ``op`` in the implementation. This is done in the two ``switch`` statements. -Second, if ``.unary_op``, or ``.binary_op`` are defined for the class, +Second, if ``unary_op``, or ``binary_op`` are defined for the class, then the handler function must have an implementation of all possible operators. This doesn’t necessarily mean that you have to have all cases in the ``switch``, but if you haven’t, then there must be a ``default`` @@ -468,15 +476,16 @@ https://github.com/v923z/micropython-usermod/tree/master/snippets/specialclass/s } } - const mp_obj_type_t specialclass_myclass_type = { - { &mp_type_type }, - .name = MP_QSTR_specialclass, - .print = myclass_print, - .make_new = myclass_make_new, - .unary_op = specialclass_unary_op, - .binary_op = specialclass_binary_op, - .locals_dict = (mp_obj_dict_t*)&myclass_locals_dict, - }; + MP_DEFINE_CONST_OBJ_TYPE( + specialclass_myclass_type, + MP_QSTR_specialclass, + MP_TYPE_FLAG_NONE, + print, myclass_print, + make_new, myclass_make_new, + unary_op, specialclass_unary_op, + binary_op, specialclass_binary_op, + locals_dict, myclass_locals_dict + ); STATIC const mp_map_elem_t specialclass_globals_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_specialclass) }, @@ -493,7 +502,7 @@ https://github.com/v923z/micropython-usermod/tree/master/snippets/specialclass/s .globals = (mp_obj_dict_t*)&mp_module_specialclass_globals, }; - MP_REGISTER_MODULE(MP_QSTR_specialclass, specialclass_user_cmodule, MODULE_SPECIALCLASS_ENABLED); + MP_REGISTER_MODULE(MP_QSTR_specialclass, specialclass_user_cmodule); https://github.com/v923z/micropython-usermod/tree/master/snippets/specialclass/micropython.mk @@ -503,13 +512,13 @@ https://github.com/v923z/micropython-usermod/tree/master/snippets/specialclass/m USERMODULES_DIR := $(USERMOD_DIR) # Add all C files to SRC_USERMOD. - SRC_USERMOD += $(USERMODULES_DIR)/specialclass.c + SRC_USERMOD_C += $(USERMODULES_DIR)/specialclass.c CFLAGS_USERMOD += -I$(USERMODULES_DIR) .. code:: bash !make clean - !make USER_C_MODULES=../../../usermod/snippets CFLAGS_EXTRA=-DMODULE_SPECIALCLASS_ENABLED=1 all + !make USER_C_MODULES=../../../usermod/snippets/specialclass .. code :: %%micropython @@ -655,9 +664,12 @@ We are now done, right? Not quite: while the required functions are implemented, they will never be called. We have to attach them to the class, so that the interpreter knows what is to do, when we try to access ``c.x``. This act of attaching the function happens in the type -definition of the class: we equate the ``.attr`` member of the structure -with our ``propertyclass_attr`` functions, so that the interpreter can -fill in the three arguments. +definition of the class: we add a new pair to our type definition. By +adding ``atty`` and its callback function which is ``propertyclass_attr`` +the interpreter can fill in the three arguments. The first argument is +the class instance, the second argument is the name of the property, and +the third argument is the return value of the function that is going to +be called, when querying for the property. And with that, we are ready to compile the code. @@ -704,13 +716,14 @@ https://github.com/v923z/micropython-usermod/tree/master/snippets/properties/pro } } - const mp_obj_type_t propertyclass_type = { - { &mp_type_type }, - .name = MP_QSTR_propertyclass, - .make_new = propertyclass_make_new, - .attr = propertyclass_attr, - .locals_dict = (mp_obj_dict_t*)&propertyclass_locals_dict, - }; + MP_DEFINE_CONST_OBJ_TYPE( + propertyclass_type, + MP_QSTR_propertyclass, + MP_TYPE_FLAG_NONE, + make_new, propertyclass_make_new, + attr, propertyclass_attr, + locals_dict, propertyclass_locals_dict, + ); STATIC const mp_map_elem_t propertyclass_globals_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_propertyclass) }, @@ -727,12 +740,12 @@ https://github.com/v923z/micropython-usermod/tree/master/snippets/properties/pro .globals = (mp_obj_dict_t*)&mp_module_propertyclass_globals, }; - MP_REGISTER_MODULE(MP_QSTR_propertyclass, propertyclass_user_cmodule, MODULE_PROPERTYCLASS_ENABLED); + MP_REGISTER_MODULE(MP_QSTR_propertyclass, propertyclass_user_cmodule); Before we compile the module, I would like to add two comments to what was said above. -First, in the function that we assigned to ``.attr``, +First, in the function that made paired with ``attr``, .. code:: c @@ -764,7 +777,7 @@ in place. Second, more examples on implementing properties can be found in `py/profile.c `__. -Just look for the ``.attr`` string, and the associated functions! +Just look for the ``attr`` string, and the associated functions! https://github.com/v923z/micropython-usermod/tree/master/snippets/properties/micropython.mk @@ -774,13 +787,13 @@ https://github.com/v923z/micropython-usermod/tree/master/snippets/properties/mic USERMODULES_DIR := $(USERMOD_DIR) # Add all C files to SRC_USERMOD. - SRC_USERMOD += $(USERMODULES_DIR)/properties.c + SRC_USERMOD_C += $(USERMODULES_DIR)/properties.c CFLAGS_USERMOD += -I$(USERMODULES_DIR) .. code:: bash !make clean - !make USER_C_MODULES=../../../usermod/snippets CFLAGS_EXTRA=-DMODULE_PROPERTYCLASS_ENABLED=1 all + !make USER_C_MODULES=../../../usermod/snippets/properties .. code :: %%micropython diff --git a/docs/source/usermods_10.rst b/docs/source/usermods_10.rst index dfd0b21..e803022 100644 --- a/docs/source/usermods_10.rst +++ b/docs/source/usermods_10.rst @@ -38,12 +38,13 @@ where the structure .. code:: c - const mp_obj_type_t vector_type = { - { &mp_type_type }, - .name = MP_QSTR_vector, - .print = vector_print, - .make_new = vector_make_new, - }; + MP_DEFINE_CONST_OBJ_TYPE( + vector_type, + MP_QSTR_vector, + MP_TYPE_FLAG_NONE, + print, vector_print, + make_new, vector_make_new + ); takes centre stage. Does this look familiar? This structure contains the new type’s name (a string, ``vector``), how it presents itself to users @@ -109,12 +110,13 @@ https://github.com/v923z/micropython-usermod/tree/master/snippets/vector/vector. return MP_OBJ_FROM_PTR(vector); } - const mp_obj_type_t vector_type = { - { &mp_type_type }, - .name = MP_QSTR_vector, - .print = vector_print, - .make_new = vector_make_new, - }; + MP_DEFINE_CONST_OBJ_TYPE( + vector_type, + MP_QSTR_vector, + MP_TYPE_FLAG_NONE, + print, vector_print, + make_new, vector_make_new + ); STATIC const mp_rom_map_elem_t vector_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_vector) }, @@ -128,7 +130,7 @@ https://github.com/v923z/micropython-usermod/tree/master/snippets/vector/vector. .globals = (mp_obj_dict_t*)&vector_module_globals, }; - MP_REGISTER_MODULE(MP_QSTR_vector, vector_user_cmodule, MODULE_VECTOR_ENABLED); + MP_REGISTER_MODULE(MP_QSTR_vector, vector_user_cmodule); https://github.com/v923z/micropython-usermod/tree/master/snippets/vector/micropython.mk @@ -138,13 +140,13 @@ https://github.com/v923z/micropython-usermod/tree/master/snippets/vector/micropy USERMODULES_DIR := $(USERMOD_DIR) # Add all C files to SRC_USERMOD. - SRC_USERMOD += $(USERMODULES_DIR)/vector.c + SRC_USERMOD_C += $(USERMODULES_DIR)/vector.c CFLAGS_USERMOD += -I$(USERMODULES_DIR) .. code:: bash !make clean - !make USER_C_MODULES=../../../usermod/snippets CFLAGS_EXTRA=-DMODULE_VECTOR_ENABLED=1 all + !make USER_C_MODULES=../../../usermod/snippets/vector .. code :: %%micropython diff --git a/snippets/arbitrarykeyword/arbitrarykeyword.c b/snippets/arbitrarykeyword/arbitrarykeyword.c index ea214a0..4185b99 100644 --- a/snippets/arbitrarykeyword/arbitrarykeyword.c +++ b/snippets/arbitrarykeyword/arbitrarykeyword.c @@ -66,4 +66,4 @@ const mp_obj_module_t arbitrarykeyword_user_cmodule = { .globals = (mp_obj_dict_t*)&arbitrarykeyword_module_globals, }; -MP_REGISTER_MODULE(MP_QSTR_arbitrarykeyword, arbitrarykeyword_user_cmodule, MODULE_ARBITRARYKEYWORD_ENABLED); +MP_REGISTER_MODULE(MP_QSTR_arbitrarykeyword, arbitrarykeyword_user_cmodule); diff --git a/snippets/arbitrarykeyword/micropython.mk b/snippets/arbitrarykeyword/micropython.mk index e1a91bd..fd388a1 100644 --- a/snippets/arbitrarykeyword/micropython.mk +++ b/snippets/arbitrarykeyword/micropython.mk @@ -1,6 +1,6 @@ USERMODULES_DIR := $(USERMOD_DIR) # Add all C files to SRC_USERMOD. -SRC_USERMOD += $(USERMODULES_DIR)/arbitrarykeyword.c +SRC_USERMOD_C += $(USERMODULES_DIR)/arbitrarykeyword.c CFLAGS_USERMOD += -I$(USERMODULES_DIR) \ No newline at end of file diff --git a/snippets/constants/constants.c b/snippets/constants/constants.c new file mode 100644 index 0000000..9bb7e1e --- /dev/null +++ b/snippets/constants/constants.c @@ -0,0 +1,41 @@ +/* + * This file is part of the micropython-usermod project, + * + * https://github.com/v923z/micropython-usermod + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Zoltán Vörös +*/ + +#include "py/obj.h" +#include "py/runtime.h" +#include "py/objstr.h" +#include "py/objtuple.h" + +#define MAGIC_CONSTANT 42 +STATIC const MP_DEFINE_STR_OBJ(version_string_obj, "1.2.3"); + +const mp_rom_obj_tuple_t version_tuple_obj = { + {&mp_type_tuple}, + 2, + { + MP_ROM_INT(1), + MP_ROM_PTR(&version_string_obj), + }, +}; + +STATIC const mp_rom_map_elem_t constants_module_globals_table[] = { + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_constants) }, + { MP_ROM_QSTR(MP_QSTR___version__), MP_ROM_PTR(&version_string_obj) }, + { MP_ROM_QSTR(MP_QSTR_magic), MP_ROM_INT(MAGIC_CONSTANT) }, + { MP_ROM_QSTR(MP_QSTR_version_tuple), MP_ROM_PTR(&version_tuple_obj) }, +}; +STATIC MP_DEFINE_CONST_DICT(constants_module_globals, constants_module_globals_table); + +const mp_obj_module_t constants_user_cmodule = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t*)&constants_module_globals, +}; + +MP_REGISTER_MODULE(MP_QSTR_constants, constants_user_cmodule); diff --git a/snippets/constants/micropython.mk b/snippets/constants/micropython.mk new file mode 100644 index 0000000..9225e15 --- /dev/null +++ b/snippets/constants/micropython.mk @@ -0,0 +1,6 @@ +USERMODULES_DIR := $(USERMOD_DIR) + +# Add all C files to SRC_USERMOD. +SRC_USERMOD_C += $(USERMODULES_DIR)/constants.c + +CFLAGS_USERMOD += -I$(USERMODULES_DIR) \ No newline at end of file diff --git a/snippets/keywordfunction/keywordfunction.c b/snippets/keywordfunction/keywordfunction.c index da583f3..5464bb6 100644 --- a/snippets/keywordfunction/keywordfunction.c +++ b/snippets/keywordfunction/keywordfunction.c @@ -41,4 +41,4 @@ const mp_obj_module_t keywordfunction_user_cmodule = { .globals = (mp_obj_dict_t*)&keywordfunction_module_globals, }; -MP_REGISTER_MODULE(MP_QSTR_keywordfunction, keywordfunction_user_cmodule, MODULE_KEYWORDFUNCTION_ENABLED); +MP_REGISTER_MODULE(MP_QSTR_keywordfunction, keywordfunction_user_cmodule); diff --git a/snippets/keywordfunction/micropython.mk b/snippets/keywordfunction/micropython.mk index 59e8f17..f1c5b1b 100644 --- a/snippets/keywordfunction/micropython.mk +++ b/snippets/keywordfunction/micropython.mk @@ -1,6 +1,6 @@ USERMODULES_DIR := $(USERMOD_DIR) # Add all C files to SRC_USERMOD. -SRC_USERMOD += $(USERMODULES_DIR)/keywordfunction.c +SRC_USERMOD_C += $(USERMODULES_DIR)/keywordfunction.c CFLAGS_USERMOD += -I$(USERMODULES_DIR) \ No newline at end of file diff --git a/snippets/properties/micropython.mk b/snippets/properties/micropython.mk index 18bef64..b81a9f8 100644 --- a/snippets/properties/micropython.mk +++ b/snippets/properties/micropython.mk @@ -1,6 +1,6 @@ USERMODULES_DIR := $(USERMOD_DIR) # Add all C files to SRC_USERMOD. -SRC_USERMOD += $(USERMODULES_DIR)/properties.c +SRC_USERMOD_C += $(USERMODULES_DIR)/properties.c CFLAGS_USERMOD += -I$(USERMODULES_DIR) \ No newline at end of file diff --git a/snippets/properties/properties.c b/snippets/properties/properties.c index 454068f..9f1aefc 100644 --- a/snippets/properties/properties.c +++ b/snippets/properties/properties.c @@ -46,13 +46,14 @@ STATIC void propertyclass_attr(mp_obj_t self_in, qstr attribute, mp_obj_t *desti } } -const mp_obj_type_t propertyclass_type = { - { &mp_type_type }, - .name = MP_QSTR_propertyclass, - .make_new = propertyclass_make_new, - .attr = propertyclass_attr, - .locals_dict = (mp_obj_dict_t*)&propertyclass_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + propertyclass_type, + MP_QSTR_propertyclass, + MP_TYPE_FLAG_NONE, + make_new, propertyclass_make_new, + attr, propertyclass_attr, + locals_dict, propertyclass_locals_dict, +); STATIC const mp_map_elem_t propertyclass_globals_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_propertyclass) }, @@ -69,4 +70,4 @@ const mp_obj_module_t propertyclass_user_cmodule = { .globals = (mp_obj_dict_t*)&mp_module_propertyclass_globals, }; -MP_REGISTER_MODULE(MP_QSTR_propertyclass, propertyclass_user_cmodule, MODULE_PROPERTYCLASS_ENABLED); +MP_REGISTER_MODULE(MP_QSTR_propertyclass, propertyclass_user_cmodule); diff --git a/snippets/sillyerrors/micropython.mk b/snippets/sillyerrors/micropython.mk index 4660cc5..ee66727 100644 --- a/snippets/sillyerrors/micropython.mk +++ b/snippets/sillyerrors/micropython.mk @@ -1,6 +1,6 @@ USERMODULES_DIR := $(USERMOD_DIR) # Add all C files to SRC_USERMOD. -SRC_USERMOD += $(USERMODULES_DIR)/sillyerrors.c +SRC_USERMOD_C += $(USERMODULES_DIR)/sillyerrors.c CFLAGS_USERMOD += -I$(USERMODULES_DIR) \ No newline at end of file diff --git a/snippets/sillyerrors/sillyerrors.c b/snippets/sillyerrors/sillyerrors.c index bf3103c..b2748ff 100644 --- a/snippets/sillyerrors/sillyerrors.c +++ b/snippets/sillyerrors/sillyerrors.c @@ -47,4 +47,4 @@ const mp_obj_module_t sillyerrors_user_cmodule = { .globals = (mp_obj_dict_t*)&sillyerrors_module_globals, }; -MP_REGISTER_MODULE(MP_QSTR_sillyerrors, sillyerrors_user_cmodule, MODULE_SILLYERRORS_ENABLED); +MP_REGISTER_MODULE(MP_QSTR_sillyerrors, sillyerrors_user_cmodule); diff --git a/snippets/simpleclass/micropython.mk b/snippets/simpleclass/micropython.mk index 0e1737e..b2cffb2 100644 --- a/snippets/simpleclass/micropython.mk +++ b/snippets/simpleclass/micropython.mk @@ -1,6 +1,6 @@ USERMODULES_DIR := $(USERMOD_DIR) # Add all C files to SRC_USERMOD. -SRC_USERMOD += $(USERMODULES_DIR)/simpleclass.c +SRC_USERMOD_C += $(USERMODULES_DIR)/simpleclass.c CFLAGS_USERMOD += -I$(USERMODULES_DIR) \ No newline at end of file diff --git a/snippets/simpleclass/simpleclass.c b/snippets/simpleclass/simpleclass.c index fe8ce85..32d8ab9 100644 --- a/snippets/simpleclass/simpleclass.c +++ b/snippets/simpleclass/simpleclass.c @@ -53,13 +53,14 @@ STATIC const mp_rom_map_elem_t myclass_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(myclass_locals_dict, myclass_locals_dict_table); -const mp_obj_type_t simpleclass_myclass_type = { - { &mp_type_type }, - .name = MP_QSTR_simpleclass, - .print = myclass_print, - .make_new = myclass_make_new, - .locals_dict = (mp_obj_dict_t*)&myclass_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + simpleclass_myclass_type, + MP_QSTR_simpleclass, + MP_TYPE_FLAG_NONE, + print, myclass_print, + make_new, myclass_make_new, + locals_dict, &myclass_locals_dict +); // Module functions STATIC mp_obj_t simpleclass_add(const mp_obj_t o_in) { @@ -85,4 +86,4 @@ const mp_obj_module_t simpleclass_user_cmodule = { .globals = (mp_obj_dict_t*)&mp_module_simpleclass_globals, }; -MP_REGISTER_MODULE(MP_QSTR_simpleclass, simpleclass_user_cmodule, MODULE_SIMPLECLASS_ENABLED); +MP_REGISTER_MODULE(MP_QSTR_simpleclass, simpleclass_user_cmodule); diff --git a/snippets/simplefunction/micropython.mk b/snippets/simplefunction/micropython.mk index 8fc72ca..bad6955 100644 --- a/snippets/simplefunction/micropython.mk +++ b/snippets/simplefunction/micropython.mk @@ -1,6 +1,6 @@ USERMODULES_DIR := $(USERMOD_DIR) # Add all C files to SRC_USERMOD. -SRC_USERMOD += $(USERMODULES_DIR)/simplefunction.c +SRC_USERMOD_C += $(USERMODULES_DIR)/simplefunction.c CFLAGS_USERMOD += -I$(USERMODULES_DIR) \ No newline at end of file diff --git a/snippets/simplefunction/simplefunction.c b/snippets/simplefunction/simplefunction.c index 8a46243..de158c2 100644 --- a/snippets/simplefunction/simplefunction.c +++ b/snippets/simplefunction/simplefunction.c @@ -30,4 +30,4 @@ const mp_obj_module_t simplefunction_user_cmodule = { .globals = (mp_obj_dict_t*)&simplefunction_module_globals, }; -MP_REGISTER_MODULE(MP_QSTR_simplefunction, simplefunction_user_cmodule, MODULE_SIMPLEFUNCTION_ENABLED); +MP_REGISTER_MODULE(MP_QSTR_simplefunction, simplefunction_user_cmodule); diff --git a/snippets/specialclass/micropython.mk b/snippets/specialclass/micropython.mk index 0e466db..95478f5 100644 --- a/snippets/specialclass/micropython.mk +++ b/snippets/specialclass/micropython.mk @@ -1,6 +1,6 @@ USERMODULES_DIR := $(USERMOD_DIR) # Add all C files to SRC_USERMOD. -SRC_USERMOD += $(USERMODULES_DIR)/specialclass.c +SRC_USERMOD_C += $(USERMODULES_DIR)/specialclass.c CFLAGS_USERMOD += -I$(USERMODULES_DIR) \ No newline at end of file diff --git a/snippets/specialclass/specialclass.c b/snippets/specialclass/specialclass.c index e47409e..675f5ef 100644 --- a/snippets/specialclass/specialclass.c +++ b/snippets/specialclass/specialclass.c @@ -73,15 +73,16 @@ STATIC mp_obj_t specialclass_binary_op(mp_binary_op_t op, mp_obj_t lhs, mp_obj_t } } -const mp_obj_type_t specialclass_myclass_type = { - { &mp_type_type }, - .name = MP_QSTR_specialclass, - .print = myclass_print, - .make_new = myclass_make_new, - .unary_op = specialclass_unary_op, - .binary_op = specialclass_binary_op, - .locals_dict = (mp_obj_dict_t*)&myclass_locals_dict, -}; +MP_DEFINE_CONST_OBJ_TYPE( + specialclass_myclass_type, + MP_QSTR_specialclass, + MP_TYPE_FLAG_NONE, + print, myclass_print, + make_new, myclass_make_new, + unary_op, specialclass_unary_op, + binary_op, specialclass_binary_op, + locals_dict, myclass_locals_dict +); STATIC const mp_map_elem_t specialclass_globals_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_specialclass) }, @@ -98,4 +99,4 @@ const mp_obj_module_t specialclass_user_cmodule = { .globals = (mp_obj_dict_t*)&mp_module_specialclass_globals, }; -MP_REGISTER_MODULE(MP_QSTR_specialclass, specialclass_user_cmodule, MODULE_SPECIALCLASS_ENABLED); +MP_REGISTER_MODULE(MP_QSTR_specialclass, specialclass_user_cmodule); diff --git a/snippets/stringarg/micropython.mk b/snippets/stringarg/micropython.mk index c8b8afd..85bccfc 100644 --- a/snippets/stringarg/micropython.mk +++ b/snippets/stringarg/micropython.mk @@ -1,6 +1,6 @@ USERMODULES_DIR := $(USERMOD_DIR) # Add all C files to SRC_USERMOD. -SRC_USERMOD += $(USERMODULES_DIR)/stringarg.c +SRC_USERMOD_C += $(USERMODULES_DIR)/stringarg.c CFLAGS_USERMOD += -I$(USERMODULES_DIR) \ No newline at end of file diff --git a/snippets/stringarg/stringarg.c b/snippets/stringarg/stringarg.c index 41eb768..0fe2c06 100644 --- a/snippets/stringarg/stringarg.c +++ b/snippets/stringarg/stringarg.c @@ -40,4 +40,4 @@ const mp_obj_module_t stringarg_user_cmodule = { .globals = (mp_obj_dict_t*)&stringarg_module_globals, }; -MP_REGISTER_MODULE(MP_QSTR_stringarg, stringarg_user_cmodule, MODULE_STRINGARG_ENABLED); +MP_REGISTER_MODULE(MP_QSTR_stringarg, stringarg_user_cmodule); diff --git a/snippets/vararg/micropython.mk b/snippets/vararg/micropython.mk index f3305c9..a119ccb 100644 --- a/snippets/vararg/micropython.mk +++ b/snippets/vararg/micropython.mk @@ -1,6 +1,6 @@ USERMODULES_DIR := $(USERMOD_DIR) # Add all C files to SRC_USERMOD. -SRC_USERMOD += $(USERMODULES_DIR)/vararg.c +SRC_USERMOD_C += $(USERMODULES_DIR)/vararg.c CFLAGS_USERMOD += -I$(USERMODULES_DIR) \ No newline at end of file diff --git a/snippets/vararg/vararg.c b/snippets/vararg/vararg.c index 99ec62a..7ec3555 100644 --- a/snippets/vararg/vararg.c +++ b/snippets/vararg/vararg.c @@ -37,4 +37,4 @@ const mp_obj_module_t vararg_user_cmodule = { .globals = (mp_obj_dict_t*)&vararg_module_globals, }; -MP_REGISTER_MODULE(MP_QSTR_vararg, vararg_user_cmodule, MODULE_VARARG_ENABLED); +MP_REGISTER_MODULE(MP_QSTR_vararg, vararg_user_cmodule); diff --git a/snippets/vector/micropython.mk b/snippets/vector/micropython.mk index 9cb94dd..b3eaf07 100644 --- a/snippets/vector/micropython.mk +++ b/snippets/vector/micropython.mk @@ -1,6 +1,6 @@ USERMODULES_DIR := $(USERMOD_DIR) # Add all C files to SRC_USERMOD. -SRC_USERMOD += $(USERMODULES_DIR)/vector.c +SRC_USERMOD_C += $(USERMODULES_DIR)/vector.c CFLAGS_USERMOD += -I$(USERMODULES_DIR) \ No newline at end of file diff --git a/snippets/vector/vector.c b/snippets/vector/vector.c index fdd8d5b..92bba93 100644 --- a/snippets/vector/vector.c +++ b/snippets/vector/vector.c @@ -53,12 +53,13 @@ STATIC mp_obj_t vector_make_new(const mp_obj_type_t *type, size_t n_args, size_t return MP_OBJ_FROM_PTR(vector); } -const mp_obj_type_t vector_type = { - { &mp_type_type }, - .name = MP_QSTR_vector, - .print = vector_print, - .make_new = vector_make_new, -}; +MP_DEFINE_CONST_OBJ_TYPE( + vector_type, + MP_QSTR_vector, + MP_TYPE_FLAG_NONE, + print, vector_print, + make_new, vector_make_new +); STATIC const mp_rom_map_elem_t vector_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_vector) }, @@ -72,4 +73,4 @@ const mp_obj_module_t vector_user_cmodule = { .globals = (mp_obj_dict_t*)&vector_module_globals, }; -MP_REGISTER_MODULE(MP_QSTR_vector, vector_user_cmodule, MODULE_VECTOR_ENABLED); +MP_REGISTER_MODULE(MP_QSTR_vector, vector_user_cmodule);