summaryrefslogtreecommitdiffstats
path: root/ffi.c
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2017-05-07 09:09:03 -0700
committerKaz Kylheku <kaz@kylheku.com>2017-05-07 09:09:03 -0700
commitfeea17487b17ca381b6d740ac50a76248f1d033c (patch)
tree03deaf4a659c7459c2600d3b916baa867c1ee4bc /ffi.c
parentb6b83892c085740529d0c38e9cf45ee1df42f97c (diff)
downloadtxr-feea17487b17ca381b6d740ac50a76248f1d033c.tar.gz
txr-feea17487b17ca381b6d740ac50a76248f1d033c.tar.bz2
txr-feea17487b17ca381b6d740ac50a76248f1d033c.zip
ffi: bugfix: all in calls must fall back on get.
* ffi.c (ffi_ptr_out_in, ffi_ptr_out_s_in): If the target type has no in handler, fall back on its get. Here, it is without regard for the copy flag, because a zero value of that flag just indicates that the ptr-out itself is passed by-value. The target object is never by value (ffi_in): Add copy flag parameter, so the full interface is exposed, like in ffi_out. Fall back on get, if there is no in and the copy flag is true. Just return the original object if the type has no in, and copy is false. (ffi_init): Registration of ffi-in adjusted to four parameters. * ffi.h (ffi_in): Declaration updated.
Diffstat (limited to 'ffi.c')
-rw-r--r--ffi.c14
1 files changed, 11 insertions, 3 deletions
diff --git a/ffi.c b/ffi.c
index 6d41bcff..f98f70fe 100644
--- a/ffi.c
+++ b/ffi.c
@@ -760,6 +760,8 @@ static val ffi_ptr_out_in(struct txr_ffi_type *tft, int copy, mem_t *src,
mem_t **loc = coerce(mem_t **, src);
if (tgtft->in != 0)
obj = tgtft->in(tgtft, 1, *loc, obj, self);
+ else
+ obj = tgtft->get(tgtft, *loc, self);
tgtft->free(*loc);
*loc = 0;
return obj;
@@ -836,6 +838,8 @@ static val ffi_ptr_out_s_in(struct txr_ffi_type *tft, int copy,
mem_t **loc = coerce(mem_t **, src);
if (tgtft->in != 0)
obj = tgtft->in(tgtft, 1, *loc, obj, self);
+ else
+ obj = tgtft->get(tgtft, *loc, self);
return obj;
}
@@ -1925,7 +1929,7 @@ val ffi_put(val obj, val type)
return buf;
}
-val ffi_in(val srcbuf, val obj, val type)
+val ffi_in(val srcbuf, val obj, val type, val copy_p)
{
val self = lit("ffi-in");
struct txr_ffi_type *tft = ffi_type_struct_checked(type);
@@ -1933,7 +1937,11 @@ val ffi_in(val srcbuf, val obj, val type)
if (lt(length_buf(srcbuf), num_fast(tft->size)))
uw_throwf(lit("~a: buffer ~s is too small for type ~s"),
self, srcbuf, type, nao);
- return tft->in(tft, 1, src, obj, self);
+ if (tft->in != 0)
+ return tft->in(tft, copy_p != nil, src, obj, self);
+ else if (copy_p)
+ return tft->get(tft, src, self);
+ return obj;
}
val ffi_get(val srcbuf, val type)
@@ -2014,7 +2022,7 @@ void ffi_init(void)
reg_fun(intern(lit("ffi-size"), user_package), func_n1(ffi_size));
reg_fun(intern(lit("ffi-put-into"), user_package), func_n3(ffi_put_into));
reg_fun(intern(lit("ffi-put"), user_package), func_n2(ffi_put));
- reg_fun(intern(lit("ffi-in"), user_package), func_n3(ffi_in));
+ reg_fun(intern(lit("ffi-in"), user_package), func_n4(ffi_in));
reg_fun(intern(lit("ffi-get"), user_package), func_n2(ffi_get));
reg_fun(intern(lit("ffi-out"), user_package), func_n4(ffi_out));
reg_varl(intern(lit("cptr-null"), user_package), cptr(0));