summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2017-05-10 06:49:21 -0700
committerKaz Kylheku <kaz@kylheku.com>2017-05-10 06:49:21 -0700
commit6947651d397d96dc14114e236468d182f003467b (patch)
treee654d3b55dd993de235a8720cb7a88bff1601c12
parente016b9c3c45835698f59c35f1e12bad861137fd0 (diff)
downloadtxr-6947651d397d96dc14114e236468d182f003467b.tar.gz
txr-6947651d397d96dc14114e236468d182f003467b.tar.bz2
txr-6947651d397d96dc14114e236468d182f003467b.zip
ffi: do arg in semantics /after/ getting return val.
What this allows is for situations when a foreign function returns the pointer that it has been passed. If that pointer is temporary storage allocated by FFI, then it is no longer valid after performing the in pass on the args. Therefore, we should decode the return value first, while the returned pointer is valid. * ffi.c (ffi_call_wrap): Move the return value get before the argument post-processing in pass.
-rw-r--r--ffi.c5
1 files changed, 4 insertions, 1 deletions
diff --git a/ffi.c b/ffi.c
index 8c99f3d9..7734d1dd 100644
--- a/ffi.c
+++ b/ffi.c
@@ -1822,6 +1822,7 @@ val ffi_call_wrap(val ffi_call_desc, val fptr, val args_in)
struct txr_ffi_type *rtft = ffi_type_struct(rtype);
void *rc = alloca(rtft->size);
int in_pass_needed = 0;
+ val ret;
for (i = 0; i < n; i++) {
val type = pop(&types);
@@ -1834,6 +1835,8 @@ val ffi_call_wrap(val ffi_call_desc, val fptr, val args_in)
ffi_call(&tfcd->cif, coerce(void (*)(void), fp), rc, values);
+ ret = rtft->get(rtft, convert(mem_t *, rc), self);
+
if (in_pass_needed) {
types = tfcd->argtypes;
args = args_in;
@@ -1846,7 +1849,7 @@ val ffi_call_wrap(val ffi_call_desc, val fptr, val args_in)
}
}
- return rtft->get(rtft, convert(mem_t *, rc), self);
+ return ret;
}
static void ffi_closure_dispatch(ffi_cif *cif, void *cret,