Skip to content
Snippets Groups Projects
Commit 8bc35163 authored by Paul Sokolovsky's avatar Paul Sokolovsky
Browse files

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.
parent 70d7a83c
No related branches found
No related tags found
No related merge requests found
...@@ -19,6 +19,7 @@ print() ...@@ -19,6 +19,7 @@ print()
perror("ffi before error") perror("ffi before error")
open("somethingnonexistent__", 0) open("somethingnonexistent__", 0)
print(errno) print(errno)
print(errno.get())
perror("ffi after error") perror("ffi after error")
print() print()
......
#include <stdlib.h>
#include <stdint.h>
#include <assert.h>
#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
}
}
// 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);
...@@ -8,3 +8,7 @@ typedef struct _mp_obj_int_t { ...@@ -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); 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_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); 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
...@@ -13,8 +13,6 @@ ...@@ -13,8 +13,6 @@
#if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_LONGLONG #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 // Python3 no longer has "l" suffix for long ints. We allow to use it
// for debugging purpose though. // for debugging purpose though.
#ifdef DEBUG #ifdef DEBUG
......
...@@ -63,6 +63,7 @@ PY_O_BASENAME = \ ...@@ -63,6 +63,7 @@ PY_O_BASENAME = \
objzip.o \ objzip.o \
sequence.o \ sequence.o \
stream.o \ stream.o \
binary.o \
builtin.o \ builtin.o \
builtinimport.o \ builtinimport.o \
builtinevex.o \ builtinevex.o \
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include "qstr.h" #include "qstr.h"
#include "obj.h" #include "obj.h"
#include "runtime.h" #include "runtime.h"
#include "binary.h"
typedef struct _mp_obj_opaque_t { typedef struct _mp_obj_opaque_t {
mp_obj_base_t base; mp_obj_base_t base;
...@@ -295,10 +296,30 @@ static void ffivar_print(void (*print)(void *env, const char *fmt, ...), void *e ...@@ -295,10 +296,30 @@ static void ffivar_print(void (*print)(void *env, const char *fmt, ...), void *e
print(env, "<ffivar @%p: 0x%x>", self->var, *(int*)self->var); print(env, "<ffivar @%p: 0x%x>", 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 = { static const mp_obj_type_t ffivar_type = {
{ &mp_const_type }, { &mp_const_type },
"ffivar", "ffivar",
.print = ffivar_print, .print = ffivar_print,
.methods = ffivar_type_methods,
}; };
// Generic opaque storage object // Generic opaque storage object
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment