diff options
| author | Jim Mussared <jim.mussared@gmail.com> | 2023-05-29 16:56:38 +1000 |
|---|---|---|
| committer | Damien George <damien@micropython.org> | 2023-09-02 00:16:16 +1000 |
| commit | 607548f32d98d955775bc02d4fc2b33a79e860ee (patch) | |
| tree | 4475bda4610f80b129014c01b2617b9223b2b278 /examples/natmod/features4/features4.c | |
| parent | f52a2cd55afb3f487801aaa62e15328134eb73a4 (diff) | |
examples/natmod: Add features4 as a class definition example.
Also provide a basic README.md for dynamic native modules.
This work was funded through GitHub Sponsors.
Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
Diffstat (limited to 'examples/natmod/features4/features4.c')
| -rw-r--r-- | examples/natmod/features4/features4.c | 73 |
1 files changed, 73 insertions, 0 deletions
diff --git a/examples/natmod/features4/features4.c b/examples/natmod/features4/features4.c new file mode 100644 index 000000000..336f4ecf6 --- /dev/null +++ b/examples/natmod/features4/features4.c @@ -0,0 +1,73 @@ +/* + This example extends on features0 but demonstrates how to define a class. + + The Factorial class constructor takes an integer, and then the calculate + method can be called to get the factorial. + + >>> import features4 + >>> f = features4.Factorial(4) + >>> f.calculate() + 24 +*/ + +// Include the header file to get access to the MicroPython API +#include "py/dynruntime.h" + +// This is type(Factorial) +mp_obj_full_type_t mp_type_factorial; + +// This is the internal state of a Factorial instance. +typedef struct { + mp_obj_base_t base; + mp_int_t n; +} mp_obj_factorial_t; + +// Essentially Factorial.__new__ (but also kind of __init__). +// Takes a single argument (the number to find the factorial of) +STATIC mp_obj_t factorial_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args_in) { + mp_arg_check_num(n_args, n_kw, 1, 1, false); + + mp_obj_factorial_t *o = mp_obj_malloc(mp_obj_factorial_t, type); + o->n = mp_obj_get_int(args_in[0]); + + return MP_OBJ_FROM_PTR(o); +} + +STATIC mp_int_t factorial_helper(mp_int_t x) { + if (x == 0) { + return 1; + } + return x * factorial_helper(x - 1); +} + +// Implements Factorial.calculate() +STATIC mp_obj_t factorial_calculate(mp_obj_t self_in) { + mp_obj_factorial_t *self = MP_OBJ_TO_PTR(self_in); + return mp_obj_new_int(factorial_helper(self->n)); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(factorial_calculate_obj, factorial_calculate); + +// Locals dict for the Factorial type (will have a single method, calculate, +// added in mpy_init). +mp_map_elem_t factorial_locals_dict_table[1]; +STATIC MP_DEFINE_CONST_DICT(factorial_locals_dict, factorial_locals_dict_table); + +// This is the entry point and is called when the module is imported +mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *args) { + // This must be first, it sets up the globals dict and other things + MP_DYNRUNTIME_INIT_ENTRY + + // Initialise the type. + mp_type_factorial.base.type = (void*)&mp_type_type; + mp_type_factorial.flags = MP_TYPE_FLAG_NONE; + mp_type_factorial.name = MP_QSTR_Factorial; + MP_OBJ_TYPE_SET_SLOT(&mp_type_factorial, make_new, factorial_make_new, 0); + factorial_locals_dict_table[0] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_calculate), MP_OBJ_FROM_PTR(&factorial_calculate_obj) }; + MP_OBJ_TYPE_SET_SLOT(&mp_type_factorial, locals_dict, (void*)&factorial_locals_dict, 1); + + // Make the Factorial type available on the module. + mp_store_global(MP_QSTR_Factorial, MP_OBJ_FROM_PTR(&mp_type_factorial)); + + // This must be last, it restores the globals dict + MP_DYNRUNTIME_INIT_EXIT +} |
