diff options
Diffstat (limited to 'examples/natmod/features2/main.c')
-rw-r--r-- | examples/natmod/features2/main.c | 83 |
1 files changed, 83 insertions, 0 deletions
diff --git a/examples/natmod/features2/main.c b/examples/natmod/features2/main.c new file mode 100644 index 0000000000..de83bf2bed --- /dev/null +++ b/examples/natmod/features2/main.c @@ -0,0 +1,83 @@ +/* This example demonstrates the following features in a native module: + - using floats + - defining additional code in Python (see test.py) + - have extra C code in a separate file (see prod.c) +*/ + +// Include the header file to get access to the MicroPython API +#include "py/dynruntime.h" + +// Include the header for auxiliary C code for this module +#include "prod.h" + +// Automatically detect if this module should include double-precision code. +// If double precision is supported by the target architecture then it can +// be used in native module regardless of what float setting the target +// MicroPython runtime uses (being none, float or double). +#if defined(__i386__) || defined(__x86_64__) || (defined(__ARM_FP) && (__ARM_FP & 8)) +#define USE_DOUBLE 1 +#else +#define USE_DOUBLE 0 +#endif + +// A function that uses the default float type configured for the current target +// This default can be overridden by specifying MICROPY_FLOAT_IMPL at the make level +STATIC mp_obj_t add(mp_obj_t x, mp_obj_t y) { + return mp_obj_new_float(mp_obj_get_float(x) + mp_obj_get_float(y)); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(add_obj, add); + +// A function that explicitly uses single precision floats +STATIC mp_obj_t add_f(mp_obj_t x, mp_obj_t y) { + return mp_obj_new_float_from_f(mp_obj_get_float_to_f(x) + mp_obj_get_float_to_f(y)); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(add_f_obj, add_f); + +#if USE_DOUBLE +// A function that explicitly uses double precision floats +STATIC mp_obj_t add_d(mp_obj_t x, mp_obj_t y) { + return mp_obj_new_float_from_d(mp_obj_get_float_to_d(x) + mp_obj_get_float_to_d(y)); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(add_d_obj, add_d); +#endif + +// A function that computes the product of floats in an array. +// This function uses the most general C argument interface, which is more difficult +// to use but has access to the globals dict of the module via self->globals. +STATIC mp_obj_t productf(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *args) { + // Check number of arguments is valid + mp_arg_check_num(n_args, n_kw, 1, 1, false); + + // Extract buffer pointer and verify typecode + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(args[0], &bufinfo, MP_BUFFER_RW); + if (bufinfo.typecode != 'f') { + mp_raise_ValueError("expecting float array"); + } + + // Compute product, store result back in first element of array + float *ptr = bufinfo.buf; + float prod = prod_array(bufinfo.len / sizeof(*ptr), ptr); + ptr[0] = prod; + + return mp_const_none; +} + +// 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 + + // Make the functions available in the module's namespace + mp_store_global(MP_QSTR_add, MP_OBJ_FROM_PTR(&add_obj)); + mp_store_global(MP_QSTR_add_f, MP_OBJ_FROM_PTR(&add_f_obj)); + #if USE_DOUBLE + mp_store_global(MP_QSTR_add_d, MP_OBJ_FROM_PTR(&add_d_obj)); + #endif + + // The productf function uses the most general C argument interface + mp_store_global(MP_QSTR_productf, MP_DYNRUNTIME_MAKE_FUNCTION(productf)); + + // This must be last, it restores the globals dict + MP_DYNRUNTIME_INIT_EXIT +} |