uctypes: Use MP_GET_BUFFER_BASE

This commit is contained in:
Jeff Epler 2025-07-20 13:30:19 -05:00
parent 6d16c8d3fe
commit 96b8c1ba68
2 changed files with 45 additions and 33 deletions

View file

@ -48,13 +48,21 @@ static const mp_obj_type_t uctypes_struct_type;
// Get size of any type descriptor
static mp_uint_t uctypes_struct_size(mp_obj_t desc_in, int layout_type, mp_uint_t *max_field_size);
#define CTYPES_FLAGS_SIZE_BITS (2)
#define CTYPES_OFFSET_SIZE_BITS (8 * sizeof(uint32_t) - 2)
typedef struct _mp_obj_uctypes_struct_t {
mp_obj_base_t base;
mp_obj_t desc;
byte *addr;
uint32_t flags;
byte *ptrbase;
uint32_t flags : CTYPES_FLAGS_SIZE_BITS;
uint32_t offset : CTYPES_OFFSET_SIZE_BITS;
} mp_obj_uctypes_struct_t;
static inline byte *struct_addr(mp_obj_uctypes_struct_t *s) {
return s->ptrbase + s->offset;
}
static MP_NORETURN void syntax_error(void) {
mp_raise_TypeError(MP_ERROR_TEXT("syntax error in uctypes descriptor"));
}
@ -80,10 +88,12 @@ mp_obj_t uctypes_struct_make_new(const mp_obj_type_t *type, size_t n_args, size_
}
mp_buffer_info_t bufinfo;
mp_obj_uctypes_struct_t *o = mp_obj_malloc(mp_obj_uctypes_struct_t, type);
if (mp_get_buffer(args[0], &bufinfo, MP_BUFFER_READ)) {
o->addr = bufinfo.buf;
if (mp_get_buffer(args[0], &bufinfo, MP_BUFFER_READ | MP_BUFFER_GET_BASE)) {
o->ptrbase = bufinfo.base;
o->offset = (char *)bufinfo.buf - (char *)bufinfo.base;
} else {
o->addr = (void *)(uintptr_t)mp_obj_get_int_truncated(args[0]);
o->ptrbase = (void *)(uintptr_t)mp_obj_get_int_truncated(args[0]);
o->offset = 0;
}
o->desc = desc;
o->flags = flags;
@ -107,9 +117,8 @@ mp_obj_t uctypes_struct_type_make_new(const mp_obj_type_t *type_in, size_t n_arg
mp_uint_t size = uctypes_struct_size(desc, type->struct_flags, &max_field_size);
mp_buffer_info_t bufinfo;
mp_obj_t bytearray = mp_obj_new_bytearray(size, NULL);
mp_get_buffer_raise(bytearray, &bufinfo, MP_BUFFER_WRITE);
if (is_ptr(desc)) {
bufinfo.len = size;
if (n_args != 1) {
mp_raise_TypeError(NULL);
}
@ -121,6 +130,9 @@ mp_obj_t uctypes_struct_type_make_new(const mp_obj_type_t *type_in, size_t n_arg
mp_get_buffer_raise(args[0], &pointee, MP_BUFFER_WRITE);
*(void **)bufinfo.buf = pointee.buf;
}
} else {
mp_obj_t bytearray = mp_obj_new_bytearray(size, NULL);
mp_get_buffer_raise(bytearray, &bufinfo, MP_BUFFER_WRITE);
}
mp_obj_t args1[] = {mp_obj_new_int((intptr_t)bufinfo.buf), desc, mp_obj_new_int(type->struct_flags)};
@ -180,7 +192,7 @@ void uctypes_struct_print(const mp_print_t *print, mp_obj_t self_in, mp_print_ki
typen = "ERROR";
}
mp_printf(print, "<%q %s %p>", (qstr)mp_obj_get_type_qstr(self_in), typen, self->addr);
mp_printf(print, "<%q %s %p>", (qstr)mp_obj_get_type_qstr(self_in), typen, struct_addr(self));
}
// Get size of scalar type descriptor
@ -477,16 +489,16 @@ static mp_obj_t uctypes_struct_attr_op(mp_obj_t self_in, qstr attr, mp_obj_t set
if (val_type <= INT64 || val_type == FLOAT32 || val_type == FLOAT64) {
if (self->flags == LAYOUT_NATIVE) {
if (set_val == MP_OBJ_NULL) {
return get_aligned(val_type, self->addr + offset, 0);
return get_aligned(val_type, struct_addr(self) + offset, 0);
} else {
set_aligned(val_type, self->addr + offset, 0, set_val);
set_aligned(val_type, struct_addr(self) + offset, 0, set_val);
return set_val; // just !MP_OBJ_NULL
}
} else {
if (set_val == MP_OBJ_NULL) {
return get_unaligned(val_type, self->addr + offset, self->flags);
return get_unaligned(val_type, struct_addr(self) + offset, self->flags);
} else {
set_unaligned(val_type, self->addr + offset, self->flags, set_val);
set_unaligned(val_type, struct_addr(self) + offset, self->flags, set_val);
return set_val; // just !MP_OBJ_NULL
}
}
@ -496,9 +508,9 @@ static mp_obj_t uctypes_struct_attr_op(mp_obj_t self_in, qstr attr, mp_obj_t set
offset &= (1 << OFFSET_BITS) - 1;
mp_uint_t val;
if (self->flags == LAYOUT_NATIVE) {
val = get_aligned_basic(val_type & 6, self->addr + offset);
val = get_aligned_basic(val_type & 6, struct_addr(self) + offset);
} else {
val = mp_binary_get_int(GET_SCALAR_SIZE(val_type & 7), val_type & 1, self->flags, self->addr + offset);
val = mp_binary_get_int(GET_SCALAR_SIZE(val_type & 7), val_type & 1, self->flags, struct_addr(self) + offset);
}
if (set_val == MP_OBJ_NULL) {
val >>= bit_offset;
@ -515,10 +527,10 @@ static mp_obj_t uctypes_struct_attr_op(mp_obj_t self_in, qstr attr, mp_obj_t set
val = (val & ~mask) | set_val_int;
if (self->flags == LAYOUT_NATIVE) {
set_aligned_basic(val_type & 6, self->addr + offset, val);
set_aligned_basic(val_type & 6, struct_addr(self) + offset, val);
} else {
mp_binary_set_int(GET_SCALAR_SIZE(val_type & 7), self->flags == LAYOUT_BIG_ENDIAN,
self->addr + offset, val);
struct_addr(self) + offset, val);
}
return set_val; // just !MP_OBJ_NULL
}
@ -544,19 +556,19 @@ static mp_obj_t uctypes_struct_attr_op(mp_obj_t self_in, qstr attr, mp_obj_t set
switch (agg_type) {
case STRUCT: {
mp_obj_t args[] = { mp_obj_new_int((mp_uint_t)(uintptr_t)self->addr + offset), sub->items[1], mp_obj_new_int(self->flags) };
mp_obj_t args[] = { mp_obj_new_int((mp_uint_t)(uintptr_t)struct_addr(self) + offset), sub->items[1], mp_obj_new_int(self->flags) };
return uctypes_struct_make_new(&uctypes_struct_type, MP_ARRAY_SIZE(args), 0, args);
}
case ARRAY: {
mp_uint_t dummy;
if (IS_SCALAR_ARRAY(sub) && IS_SCALAR_ARRAY_OF_BYTES(sub)) {
return mp_obj_new_bytearray_by_ref(uctypes_struct_agg_size(sub, self->flags, &dummy), self->addr + offset);
return mp_obj_new_bytearray_by_ref(uctypes_struct_agg_size(sub, self->flags, &dummy), struct_addr(self) + offset);
}
// Fall thru to return uctypes struct object
MP_FALLTHROUGH
}
case PTR: {
mp_obj_t args[] = { mp_obj_new_int((mp_uint_t)(uintptr_t)self->addr + offset), deref, mp_obj_new_int(self->flags) };
mp_obj_t args[] = { mp_obj_new_int((mp_uint_t)(uintptr_t)struct_addr(self) + offset), deref, mp_obj_new_int(self->flags) };
return uctypes_struct_make_new(&uctypes_struct_type, MP_ARRAY_SIZE(args), 0, args);
}
}
@ -640,13 +652,13 @@ mp_obj_t uctypes_struct_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t val
// array of scalars
if (self->flags == LAYOUT_NATIVE) {
if (value == MP_OBJ_SENTINEL) {
return get_aligned(val_type, self->addr, index);
return get_aligned(val_type, struct_addr(self), index);
} else {
set_aligned(val_type, self->addr, index, value);
set_aligned(val_type, struct_addr(self), index, value);
return value; // just !MP_OBJ_NULL
}
} else {
byte *p = self->addr + uctypes_struct_scalar_size(val_type) * index;
byte *p = struct_addr(self) + uctypes_struct_scalar_size(val_type) * index;
if (value == MP_OBJ_SENTINEL) {
return get_unaligned(val_type, p, self->flags);
} else {
@ -657,14 +669,14 @@ mp_obj_t uctypes_struct_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t val
} else if (value == MP_OBJ_SENTINEL) {
mp_uint_t dummy = 0;
mp_uint_t size = uctypes_struct_size(t->items[2], self->flags, &dummy);
mp_obj_t args[] = { mp_obj_new_int((mp_uint_t)(uintptr_t)self->addr + size * index), t->items[2], mp_obj_new_int(self->flags) };
mp_obj_t args[] = { mp_obj_new_int((mp_uint_t)(uintptr_t)struct_addr(self) + size * index), t->items[2], mp_obj_new_int(self->flags) };
return uctypes_struct_make_new(&uctypes_struct_type, MP_ARRAY_SIZE(args), 0, args);
} else {
return MP_OBJ_NULL; // op not supported
}
} else if (agg_type == PTR) {
byte *p = *(void **)self->addr;
byte *p = *(void **)struct_addr(self);
if (mp_obj_is_small_int(t->items[1])) {
uint val_type = GET_TYPE(MP_OBJ_SMALL_INT_VALUE(t->items[1]), VAL_TYPE_BITS);
if (value == MP_OBJ_SENTINEL) {
@ -695,7 +707,7 @@ mp_obj_t uctypes_struct_unary_op(mp_unary_op_t op, mp_obj_t self_in) {
mp_int_t offset = MP_OBJ_SMALL_INT_VALUE(t->items[0]);
uint agg_type = GET_TYPE(offset, AGG_TYPE_BITS);
if (agg_type == PTR) {
byte *p = *(void **)self->addr;
byte *p = *(void **)struct_addr(self);
return mp_obj_new_int_from_uint((uintptr_t)p);
}
}
@ -712,9 +724,13 @@ mp_int_t uctypes_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo, mp_uint
mp_uint_t max_field_size = 0;
mp_uint_t size = uctypes_struct_size(self->desc, self->flags, &max_field_size);
bufinfo->buf = self->addr;
bufinfo->buf = struct_addr(self);
bufinfo->len = size;
bufinfo->typecode = BYTEARRAY_TYPECODE;
if (flags & MP_BUFFER_GET_BASE) {
bufinfo->base = (void *)self->ptrbase;
}
return 0;
}

View file

@ -225,7 +225,7 @@ static mp_obj_t memoryview_make_new(const mp_obj_type_t *type_in, size_t n_args,
mp_arg_check_num(n_args, n_kw, 1, 1, false);
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(args[0], &bufinfo, MP_BUFFER_READ);
mp_get_buffer_raise(args[0], &bufinfo, MP_BUFFER_READ | MP_BUFFER_GET_BASE);
mp_obj_array_t *self = MP_OBJ_TO_PTR(mp_obj_new_memoryview(bufinfo.typecode,
bufinfo.len / mp_binary_get_size('@', bufinfo.typecode, NULL),
@ -233,12 +233,8 @@ static mp_obj_t memoryview_make_new(const mp_obj_type_t *type_in, size_t n_args,
// If the input object is a memoryview then need to point the items of the
// new memoryview to the start of the buffer so the GC can trace it.
if (mp_obj_get_type(args[0]) == &mp_type_memoryview) {
mp_obj_array_t *other = MP_OBJ_TO_PTR(args[0]);
self->memview_offset = other->memview_offset;
self->items = other->items;
}
self->memview_offset = (char *)bufinfo.buf - (char *)bufinfo.base;
self->items = bufinfo.base;
// test if the object can be written to
if (mp_get_buffer(args[0], &bufinfo, MP_BUFFER_RW)) {
self->typecode |= MP_OBJ_ARRAY_TYPECODE_FLAG_RW; // indicate writable buffer