unix/modffi: Fix conversion between Python integers and ffi types.
This commit fixes the following problems converting to/from Python integers and ffi types: - integers of 8 and 16 bits not working on big endian - integers of 64 bits not working on 32 bits architectures - unsigned returns were converted to signed Python integers Fixes issue #7269.
This commit is contained in:
parent
20a8f4f7ec
commit
525a920ca5
@ -35,6 +35,7 @@
|
|||||||
#include "py/runtime.h"
|
#include "py/runtime.h"
|
||||||
#include "py/binary.h"
|
#include "py/binary.h"
|
||||||
#include "py/mperrno.h"
|
#include "py/mperrno.h"
|
||||||
|
#include "py/objint.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* modffi uses character codes to encode a value type, based on "struct"
|
* modffi uses character codes to encode a value type, based on "struct"
|
||||||
@ -59,6 +60,11 @@
|
|||||||
// This union is large enough to hold any supported argument/return value.
|
// This union is large enough to hold any supported argument/return value.
|
||||||
typedef union _ffi_union_t {
|
typedef union _ffi_union_t {
|
||||||
ffi_arg ffi;
|
ffi_arg ffi;
|
||||||
|
unsigned char B;
|
||||||
|
unsigned short int H;
|
||||||
|
unsigned int I;
|
||||||
|
unsigned long int L;
|
||||||
|
unsigned long long int Q;
|
||||||
float flt;
|
float flt;
|
||||||
double dbl;
|
double dbl;
|
||||||
} ffi_union_t;
|
} ffi_union_t;
|
||||||
@ -177,6 +183,20 @@ STATIC mp_obj_t return_ffi_value(ffi_union_t *val, char type) {
|
|||||||
return mp_obj_new_float_from_d(val->dbl);
|
return mp_obj_new_float_from_d(val->dbl);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
case 'b':
|
||||||
|
case 'h':
|
||||||
|
case 'i':
|
||||||
|
case 'l':
|
||||||
|
return mp_obj_new_int((signed)val->ffi);
|
||||||
|
case 'B':
|
||||||
|
case 'H':
|
||||||
|
case 'I':
|
||||||
|
case 'L':
|
||||||
|
return mp_obj_new_int_from_uint(val->ffi);
|
||||||
|
case 'q':
|
||||||
|
return mp_obj_new_int_from_ll(val->Q);
|
||||||
|
case 'Q':
|
||||||
|
return mp_obj_new_int_from_ull(val->Q);
|
||||||
case 'O':
|
case 'O':
|
||||||
return (mp_obj_t)(intptr_t)val->ffi;
|
return (mp_obj_t)(intptr_t)val->ffi;
|
||||||
default:
|
default:
|
||||||
@ -365,6 +385,48 @@ STATIC void ffifunc_print(const mp_print_t *print, mp_obj_t self_in, mp_print_ki
|
|||||||
mp_printf(print, "<ffifunc %p>", self->func);
|
mp_printf(print, "<ffifunc %p>", self->func);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
STATIC unsigned long long ffi_get_int_value(mp_obj_t o) {
|
||||||
|
if (mp_obj_is_small_int(o)) {
|
||||||
|
return MP_OBJ_SMALL_INT_VALUE(o);
|
||||||
|
} else {
|
||||||
|
unsigned long long res;
|
||||||
|
mp_obj_int_to_bytes_impl(o, MP_ENDIANNESS_BIG, sizeof(res), (byte *)&res);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
STATIC ffi_union_t ffi_int_obj_to_ffi_union(mp_obj_t o, const char argtype) {
|
||||||
|
ffi_union_t ret;
|
||||||
|
if ((argtype | 0x20) == 'q') {
|
||||||
|
ret.Q = ffi_get_int_value(o);
|
||||||
|
return ret;
|
||||||
|
} else {
|
||||||
|
mp_uint_t val = mp_obj_int_get_truncated(o);
|
||||||
|
switch (argtype) {
|
||||||
|
case 'b':
|
||||||
|
case 'B':
|
||||||
|
ret.B = val;
|
||||||
|
break;
|
||||||
|
case 'h':
|
||||||
|
case 'H':
|
||||||
|
ret.H = val;
|
||||||
|
break;
|
||||||
|
case 'i':
|
||||||
|
case 'I':
|
||||||
|
ret.I = val;
|
||||||
|
break;
|
||||||
|
case 'l':
|
||||||
|
case 'L':
|
||||||
|
ret.L = val;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ret.ffi = val;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
STATIC mp_obj_t ffifunc_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {
|
STATIC mp_obj_t ffifunc_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {
|
||||||
(void)n_kw;
|
(void)n_kw;
|
||||||
mp_obj_ffifunc_t *self = MP_OBJ_TO_PTR(self_in);
|
mp_obj_ffifunc_t *self = MP_OBJ_TO_PTR(self_in);
|
||||||
@ -387,7 +449,7 @@ STATIC mp_obj_t ffifunc_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const
|
|||||||
} else if (a == mp_const_none) {
|
} else if (a == mp_const_none) {
|
||||||
values[i].ffi = 0;
|
values[i].ffi = 0;
|
||||||
} else if (mp_obj_is_int(a)) {
|
} else if (mp_obj_is_int(a)) {
|
||||||
values[i].ffi = mp_obj_int_get_truncated(a);
|
values[i] = ffi_int_obj_to_ffi_union(a, *argtype);
|
||||||
} else if (mp_obj_is_str(a)) {
|
} else if (mp_obj_is_str(a)) {
|
||||||
const char *s = mp_obj_str_get_str(a);
|
const char *s = mp_obj_str_get_str(a);
|
||||||
values[i].ffi = (ffi_arg)(intptr_t)s;
|
values[i].ffi = (ffi_arg)(intptr_t)s;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user