84 lines
3.2 KiB
C
84 lines
3.2 KiB
C
/* 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(MP_ERROR_TEXT("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
|
|
}
|