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
commit2e0385880600fb0edee85a8960ed3160086a42f1 (patch)
treee654d3b55dd993de235a8720cb7a88bff1601c12
parent471149c262613e4b69fc14b9599fe541106084e4 (diff)
downloadtxr-2e0385880600fb0edee85a8960ed3160086a42f1.tar.gz
txr-2e0385880600fb0edee85a8960ed3160086a42f1.tar.bz2
txr-2e0385880600fb0edee85a8960ed3160086a42f1.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,