diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2017-05-10 06:49:21 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2017-05-10 06:49:21 -0700 |
commit | 2e0385880600fb0edee85a8960ed3160086a42f1 (patch) | |
tree | e654d3b55dd993de235a8720cb7a88bff1601c12 /ffi.c | |
parent | 471149c262613e4b69fc14b9599fe541106084e4 (diff) | |
download | txr-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.
Diffstat (limited to 'ffi.c')
-rw-r--r-- | ffi.c | 5 |
1 files changed, 4 insertions, 1 deletions
@@ -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, |