From 8bc3516389cd148ebeaa58ceaf3d3f7fb13440d8 Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Fri, 14 Feb 2014 17:16:35 +0200 Subject: [PATCH] ffi: Implement ffivar.get()/set() methods. Done by introducing another factored out helper API in binary.c. This API can be reused also by array and struct modules. --- examples/unix/ffi_example.py | 1 + py/binary.c | 96 ++++++++++++++++++++++++++++++++++++ py/binary.h | 7 +++ py/objint.h | 4 ++ py/objint_longlong.c | 2 - py/py.mk | 1 + unix/ffi.c | 21 ++++++++ 7 files changed, 130 insertions(+), 2 deletions(-) create mode 100644 py/binary.c create mode 100644 py/binary.h diff --git a/examples/unix/ffi_example.py b/examples/unix/ffi_example.py index 0ac12203e6..bc3919d40a 100644 --- a/examples/unix/ffi_example.py +++ b/examples/unix/ffi_example.py @@ -19,6 +19,7 @@ print() perror("ffi before error") open("somethingnonexistent__", 0) print(errno) +print(errno.get()) perror("ffi after error") print() diff --git a/py/binary.c b/py/binary.c new file mode 100644 index 0000000000..a738dd62a9 --- /dev/null +++ b/py/binary.c @@ -0,0 +1,96 @@ +#include +#include +#include + +#include "misc.h" +#include "mpconfig.h" +#include "qstr.h" +#include "obj.h" +#include "objint.h" +#include "binary.h" + +// Helpers to work with binary-encoded data + +mp_obj_t mp_binary_get_val(char typecode, void *p, int index) { + int val = 0; + switch (typecode) { + case 'b': + val = ((int8_t*)p)[index]; + break; + case BYTEARRAY_TYPECODE: + case 'B': + val = ((uint8_t*)p)[index]; + break; + case 'h': + val = ((int16_t*)p)[index]; + break; + case 'H': + val = ((uint16_t*)p)[index]; + break; + case 'i': + case 'l': + return mp_obj_new_int(((int32_t*)p)[index]); + case 'I': + case 'L': + return mp_obj_new_int_from_uint(((uint32_t*)p)[index]); +#if MICROPY_LONGINT_IMPL != MICROPY_LONGINT_IMPL_NONE + case 'q': + case 'Q': + // TODO: Explode API more to cover signedness + return mp_obj_new_int_from_ll(((long long*)p)[index]); +#endif +#if MICROPY_ENABLE_FLOAT + case 'f': + return mp_obj_new_float(((float*)p)[index]); + case 'd': + return mp_obj_new_float(((double*)p)[index]); +#endif + } + return MP_OBJ_NEW_SMALL_INT(val); +} + +void mp_binary_set_val(char typecode, void *p, int index, mp_obj_t val_in) { + machine_int_t val = 0; + if (MP_OBJ_IS_INT(val_in)) { + val = mp_obj_int_get(val_in); + } + + switch (typecode) { + case 'b': + ((int8_t*)p)[index] = val; + break; + case BYTEARRAY_TYPECODE: + case 'B': + val = ((uint8_t*)p)[index] = val; + break; + case 'h': + val = ((int16_t*)p)[index] = val; + break; + case 'H': + val = ((uint16_t*)p)[index] = val; + break; + case 'i': + case 'l': + ((int32_t*)p)[index] = val; + break; + case 'I': + case 'L': + ((uint32_t*)p)[index] = val; + break; +#if MICROPY_LONGINT_IMPL != MICROPY_LONGINT_IMPL_NONE + case 'q': + case 'Q': + assert(0); + ((long long*)p)[index] = val; + break; +#endif +#if MICROPY_ENABLE_FLOAT + case 'f': + ((float*)p)[index] = mp_obj_float_get(val_in); + break; + case 'd': + ((double*)p)[index] = mp_obj_float_get(val_in); + break; +#endif + } +} diff --git a/py/binary.h b/py/binary.h new file mode 100644 index 0000000000..0bd6ad17ac --- /dev/null +++ b/py/binary.h @@ -0,0 +1,7 @@ +// Use special typecode to differentiate repr() of bytearray vs array.array('B') +// (underlyingly they're same). +#define BYTEARRAY_TYPECODE 0 + +int mp_binary_get_size(char typecode); +mp_obj_t mp_binary_get_val(char typecode, void *p, int index); +void mp_binary_set_val(char typecode, void *p, int index, mp_obj_t val_in); diff --git a/py/objint.h b/py/objint.h index 6662be1ef3..df3b81b79f 100644 --- a/py/objint.h +++ b/py/objint.h @@ -8,3 +8,7 @@ typedef struct _mp_obj_int_t { void int_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind); mp_obj_t int_unary_op(int op, mp_obj_t o_in); mp_obj_t int_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in); + +#if MICROPY_LONGINT_IMPL != MICROPY_LONGINT_IMPL_NONE +mp_obj_t mp_obj_new_int_from_ll(long long val); +#endif diff --git a/py/objint_longlong.c b/py/objint_longlong.c index f637807905..7412cc09c3 100644 --- a/py/objint_longlong.c +++ b/py/objint_longlong.c @@ -13,8 +13,6 @@ #if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_LONGLONG -STATIC mp_obj_t mp_obj_new_int_from_ll(long long val); - // Python3 no longer has "l" suffix for long ints. We allow to use it // for debugging purpose though. #ifdef DEBUG diff --git a/py/py.mk b/py/py.mk index e29d7b6cad..1d9eb535ae 100644 --- a/py/py.mk +++ b/py/py.mk @@ -63,6 +63,7 @@ PY_O_BASENAME = \ objzip.o \ sequence.o \ stream.o \ + binary.o \ builtin.o \ builtinimport.o \ builtinevex.o \ diff --git a/unix/ffi.c b/unix/ffi.c index b83fc120a9..a82e4e3386 100644 --- a/unix/ffi.c +++ b/unix/ffi.c @@ -10,6 +10,7 @@ #include "qstr.h" #include "obj.h" #include "runtime.h" +#include "binary.h" typedef struct _mp_obj_opaque_t { mp_obj_base_t base; @@ -295,10 +296,30 @@ static void ffivar_print(void (*print)(void *env, const char *fmt, ...), void *e print(env, "", self->var, *(int*)self->var); } +static mp_obj_t ffivar_get(mp_obj_t self_in) { + mp_obj_ffivar_t *self = self_in; + return mp_binary_get_val(self->type, self->var, 0); +} +MP_DEFINE_CONST_FUN_OBJ_1(ffivar_get_obj, ffivar_get); + +static mp_obj_t ffivar_set(mp_obj_t self_in, mp_obj_t val_in) { + mp_obj_ffivar_t *self = self_in; + mp_binary_set_val(self->type, self->var, 0, val_in); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(ffivar_set_obj, ffivar_set); + +static const mp_method_t ffivar_type_methods[] = { + { "get", &ffivar_get_obj }, + { "set", &ffivar_set_obj }, + { NULL, NULL }, +}; + static const mp_obj_type_t ffivar_type = { { &mp_const_type }, "ffivar", .print = ffivar_print, + .methods = ffivar_type_methods, }; // Generic opaque storage object