summaryrefslogtreecommitdiff
path: root/ports/unix/modffi.c
diff options
context:
space:
mode:
Diffstat (limited to 'ports/unix/modffi.c')
-rw-r--r--ports/unix/modffi.c64
1 files changed, 63 insertions, 1 deletions
diff --git a/ports/unix/modffi.c b/ports/unix/modffi.c
index 5c2595ec5..12a33619e 100644
--- a/ports/unix/modffi.c
+++ b/ports/unix/modffi.c
@@ -35,6 +35,7 @@
#include "py/runtime.h"
#include "py/binary.h"
#include "py/mperrno.h"
+#include "py/objint.h"
/*
* 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.
typedef union _ffi_union_t {
ffi_arg ffi;
+ unsigned char B;
+ unsigned short int H;
+ unsigned int I;
+ unsigned long int L;
+ unsigned long long int Q;
float flt;
double dbl;
} 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);
}
#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':
return (mp_obj_t)(intptr_t)val->ffi;
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);
}
+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) {
(void)n_kw;
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) {
values[i].ffi = 0;
} 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)) {
const char *s = mp_obj_str_get_str(a);
values[i].ffi = (ffi_arg)(intptr_t)s;