| Commit message (Collapse) | Author | Age | Files | Lines |
... | |
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This anticipates a redesign of variable arrays. Variable
arrays will have their own put, in, get and out functions,
which will share some implementation.
* ffi.c (ffi_array_in_common): New function.
(ffi_array_in): Bulk of code replaced by call to
ffi_array_in_common.
(ffi_array_put_common, ffi_array_out_common,
ffi_array_get_common): New functions.
(ffi_array_put, ffi_array_out, ffi_array_get): Reduced to thin
wrappers.
|
|
|
|
|
|
| |
* ffi.c (ffi_make_call_desc): Throw if any argument
type is something with zero size. Throw if the return
type has zero size and isn't the type void.
|
|
|
|
|
|
|
| |
* ffi.c (ffi_char_array_get, ffi_wchar_array_get,
ffi_bchar_array_get): New static functions.
(ffi_array_in, ffi_array_get): Replace common code
with calls to code moved out into functons.
|
|
|
|
|
|
|
|
|
| |
Arrays can be varray, whose size is just pointer size.
The string extraction operations shouldn't be referring
to the size.
* ffi.c (ffi_array_in, ffi_array_et): Use nelem instead
of tft->size.
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
We want to be able to extract null-terminated UTF-8 strings
from arrays, without trailing junk, yet retain the ability to
extract the entire array including embedded nulls. The natural
way is to use the array/zarray distinction.
* ffi.c (ffi_array_in, ffi_array_get): Don't try to guess
whether the array is null terminated; just rely on the
null_term flag, and treat accordingly.
* txr.1: Doc updated.
|
|
|
|
|
| |
* ffi.c (cptr_make): Function removed.
(ffi_init): Registration of cptr and cptr-null removed.
|
|
|
|
|
|
|
|
|
| |
* ffi.c (ffi_float_put, ffi_double_put): Support a useful
type looseness by allowing integers and character Lisp
values to pair with FFI floating-point types, imitating
the conversion which happens in C function calls.
* txr.1: Updated.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* ffi.c (ffi_i8_put, ffi_u8_put, ffi_i16_put, ffi_i16_get,
ffi_u16_put, ffi_u16_get, ffi_i32_put, ffi_i32_get,
ffi_u32_put, ffi_u32_get, ffi_i64_put, ffi_i64_get,
ffi_u64_put, ffi_u64_get, ffi_char_put, ffi_char_get,
ffi_uchar_get, ffi_short_get, ffi_ushort_put, ffi_ushort_get,
ffi_int_put, ffi_int_get, ffi_uint_put, ffi_uint_get,
ffi_long_put, ffi_long_get, ffi_ulong_put, ffi_ulong_get,
ffi_float_put, ffi_float_get, ffi_double_put, ffi_double_get,
ffi_wchar_put, ffi_wchar_get, ffi_cptr_put, ffi_cptr_get):
memcpy operations replaced by by assignments through pointer
casts.
|
|
|
|
|
|
| |
* ffi.c (ffi_closure_print_op): Add information to the
printed representation: the Lisp function, and call desc.
Eliminate spurious # character before closing angle bracket.
|
|
|
|
|
|
|
|
|
|
| |
* ffi.c (ffi_struct_put, ffi_struct_out): Just skip the space
corresponding to the anonymous padding member; don't memset
with zeros. Doing this is inconsistent because we are not
zero-filling the ordinary alignment padding between members
and at the end of the struct. If the uninitialized garbage
is a problem in some uses, we can provide a variation of
the struct type which is zero initialized.
|
|
|
|
|
|
|
| |
* ffi.c (ffi_array_put, ffi_array_out): If dealign with
a variable array that is null terminated, let's add one to
nelem, so that all elements of the Lisp sequence are
converted, and then a null.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Backing out of the scheme of (ptr buf) passing the
address of the internal pointer within buf objects.
Also giving buf in handlers, to prevent the fallback
on get.
* buf.c (buf_addr_of): Function removed.
* buf.h (buf_addr_of): Declaration removed.
* ffi.c (ffi_buf_in, ffi_buf_d_in): New functions.
(ffi_buf_alloc): Function removed.
(ffi_type_compile, ffi_init_types): Remove specialty alloc and
free functions from buffers, so the regular fixed allocator is
used. Give buffers the new in functions.
|
|
|
|
|
|
|
|
|
|
| |
* ffi.c (ffi_ptr_in_in): Don't just free the buffer for
the pointer itself, but call the in handler of the target
type if it has one. Pass a false copy flag to it, so that
that a ptr-in pass semantically resembles a by-value pass.
(ffi_ptr_in_d_in): New static function.
(ffi_type_compile): Give ptr-in-d type the ffi_ptr_in_d_in
function.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* 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.
|
|
|
|
|
|
|
|
|
|
| |
* ffi.c (ffi_struct_in, ffi_array_in): Only fall back on get
if the copy flag is true. If the copy flag is false, we must
not extract. That's not ony as an optimization (no point in
extracting back from by-value objects). We also avoid
extracting from pointers we don't own, like in the case
of str-d, where the pointer is owned by the foreign function
and may have been freed.
|
|
|
|
|
|
|
| |
* ffi.c (ffi_struct_out, ffi_array_out): For any element
which has no out function, do a put if the copy flag is
true. Otherwise callbacks cannot update members in
aggregates passed by pointer.
|
|
|
|
|
|
| |
* ffi.c (ffi_bstr_in): New function.
(ffi_init_types): Give bstr type ffi_bstr_in as the in
function.
|
|
|
|
|
|
|
|
|
| |
* ffi.c (ffi_closure_dispatch): Only call out on those
arguments which have a non-null out pointer, otherwise we will
crash. Those non-null values are the reason we even execute
that loop at all.
(ffi_out): Do a put for basic types (which have no out
handler).
|
|
|
|
|
|
|
|
|
|
| |
Omission of the dimension will be expressed by actual omission
rather than the void placeholder. It's just a harmless bit of
parsing providing a reasonably intuitive syntax that doesn't
leave readers wondering what void is doing there.
* ffi.c (ffi_type_compile): Rearrange array parsing code.
Also diagnose if the form has more than thre elements.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This solves the second issue described in parent
commit. When a str type is passed in-out using
(ptr str) in a struct or array, the struct or array
is not picking up the new string. The pointer is
freed, but the old object persists.
* ffi.c (ffi_str_in): Function renamed to ffi_str_in. If the
copy flag is true, retrieves a string from the pointer and
that string is returned instead of the incoming one, mapping a
null pointer to nil. Either way, the pointer is freed. Since
ffi_ptr_out_in passes 1 for the copy flag, that ensures we
extract the new string and plant it into the array.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
We have two problems. Firstly, the in handler is being
called on by-value struct and array arguments, and is
wastefully updating the members in the Lisp object.
The second issue is opposite the str type fails to retrieve
the updated string because ffi_freeing_in just frees.
We don't address this issue here, but the groundwork
is laid to fix it in the next commit.
* ffi.c (struct txr_ffi_type *): Add a copy flag argument
to the in virtual function.
(ffi_freeing_in, ffi_ptr_in_in, ffi_ptr_out_in,
(ffi_ptr_out_in, ffi_ptr_out_s_in): Take new copy argument.
Don't pass it down to the recursive in; pass 1.
(ffi_struct_in, ffi_array_in): Take copy argument and pass it
down.
(make_ffi_type_pointer): Type of in parameter updated.
(ffi_call_wrap): Pass 0 to top level in functions.
(ffi_in): Pass to in, so new object is returned.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
If an array dimension is void, it is a varray. The C
representation is pointer. The size is inferred
from the length of the object. Doesn't support get
method.
* ffi.c (struct txr_ffi_type): New bitfield flag, is_varray.
(ffi_varray_alloc): New function.
(ffi_array_in, ffi_array_put, ffi_array_out): Check is_varray
flag and use dynamic array size from object.
(ffi_type_compile): If the array dimension is the symbol
void, create a varray: a mongrel created using
make_ffi_type_pointer, but using the array functions,
plus alloc and free handlers, and the is_varray flag
being set.
|
|
|
|
|
|
|
|
| |
* ffi.c (make_ffi_type_pointer): The underlying ffi type
is always ffi_type_pointer, so the parameter for specifying
it is removed, and it is hard-coded.
(ffi_type_compile): Remove &ffi_type_pointer argument from
a half dozen calls.
|
|
|
|
|
|
|
|
|
| |
This will support a sizeof macro.
* ffi.c (ffi_size): New function.
(ffi_init): Register ffi-size intrinsic.
* ffi.h (ffi_size): Declared.
|
|
|
|
|
|
|
|
|
|
| |
* ffi.c (ffi_put_into, ffi_put, ffi_in, ffi_get, ffi_out):
New functions.
(ffi_init): ffi-put-into, ffi-put, ffi-in, ffi-get, ffi-out:
intrinsics registered.
* ffi.h (ffi_put_into, ffi_put, ffi_in, ffi_get, ffi_out):
Declared.
|
|
|
|
|
| |
* ffi.c (ffi_type_compile): Check for a negative buffer
size and throw.
|
|
|
|
|
|
| |
* ffi.c (ffi_type_compile): Throw error if the dimension
is negative in any array operator, or also if it is zero in a
zarray operator.
|
|
|
|
|
|
|
|
|
|
| |
* ffi.c (struct txr_ffi_type): New bitfield flag, bchar_conv.
(ffi_array_in, ffi_array_get): Handle bchar_conv.
(ffi_type_compile): Set bchar_conv flag for array of bchar.
* lib.c (string_8bit_size): New function.
* lib.h (string_8bit_size): Declared.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
A zarray of length N is requiring the Lisp vector to be
of length N.
* ffi.c (ffi_array_put): Reorder logic in the loop so that
when we are putting out the terminating null element of a
zarray, we do not access the corresponding element of the Lisp
vector. Thus if the zarray is N elements wide, the Lisp
vector need only be at least N-1 elements wide, not N.
(ffi_array_in): Copy the null element of a zarray to the
vector only if the vector object at least N elements.
If the vector is nil so that we have to construct one,
construct a vector of N-1 for a zarray.
(ffi_array_get): For a zarray, construct a vector of N-1
elements. Do not even fetch the null.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The bstr type is like str, but doesn't perform UTF-8
conversion. The C data is assumed to be null terminated byte
strings representing code points U+0000 through U+00FF.
* ffi.c (bstr_s, bstr_d_s): New symbol variables.
(ffi_bstr_put, ffi_bstr_get, ffi_bstr_d_get): New static
functions.
(ffi_init_types): Register bstr and bstr-d types.
(ffi_init): Initialize bstr_s and bstr_d_s.
* ffi.h (bstr_s, bstr_d_s): Declared.
* lib.c (chk_strdup_8bit, string_8bit): New function.
* lib.h (chk_strdup_8bit, string_8bit): Declared.
|
|
|
|
|
|
|
|
|
|
|
|
| |
bchar is like uchar, except that in the decode direction,
it produces character objects rather than integers.
* ffi.c (bchar_s): New symbol variable.
(ffi_bchar_get): New static function.
(ffi_init_types): Register bchar type.
(ffi_init): Initialize bchar_s.
* ffi.h (bchar_s): Declared.
|
|
|
|
|
|
| |
* ffi.c (ffi_str_d_put): Function removed. It is identical to
ffi_str_put.
(ffi_init_types): Use ffi_str_put for the str-d type.
|
|
|
|
|
|
| |
* ffi.c (ffi_char_get): Get a char object as a Lisp character,
rather than number. Users who want a byte to convert to a
an integer can use one of the types int8 or uint8 instead.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
One more ptr type is useful. This type is for objects returned via
pointers embedded in arrays or structures, whereby the callee
establishes both the pointer and the data.
This is similar to ptr-out-d; the difference is that the
data has an indefinite lifetime ("s" denotes "static")
and so the pointer is not freed after the call takes place
and the data is extracted into Lisp objects.
* ffi.c (ptr_out_s_s): New symbol variable.
(ffi_ptr_out_s_in): New function.
(ffi_type_compile): Handle new ptr_out_s_s.
(ffi_init): Initialize ptr_out_s.
* ffi.h (ptr_out_s_s): Declared.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Since the callee allocates the buffer for a ptr-out-d, the FFI
mechanism should not also be allocating a buffer to receive
the object. The buffer pointer will just be overwritten by the
callee with its own dynamic pointer. We should pass a null
pointer which the callee fills in (making a ptr-out-d not
suitable as a by-value parameter).
Initially, ptr-out-d was envisioned for return values only
and for use in callbacks, which is why I neglected this
aspect.
* ffi.c (ffi_ptr_out_null_put): New static function.
(ffi_type_compile): Use ffi_ptr_out_null_put for the
ffi_ptr_out_d case, so caller places a null pointer, then
frees the pointer that the callee places there.
|
|
|
|
|
|
| |
* ffi.c (ffi_ptr_put): Rnamed to ffi_ptr_in_put.
(ffi_type_compile): All uses of ffi_ptr_put replaced with
ffi_ptr_in_put.
|
|
|
|
|
|
|
|
|
|
| |
* ffi.c (ffi_ptr_in_put): Static function removed. It was
functionally identical to ffi_ptr_put, plus a memory leak bug
in the nil object case.
(ffi_ptr_in_d_put): Static function removed, also identical to
ffi_ptr_put.
(ffi_type_compile): Replace references to removed functions
with ffi_ptr_put.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The problem is as follows. When an aggregate is being passed
by pointer, the C code can update its elements. If any of
those elements are declared arrays or structs to FFI, but the
actual Lips object has nil slot values for those elements,
then things don't work, because nil cannot be mutated in
place to become a filled vector or struct.
The solution is to alter the in virtual function so that it
can return a value, just like the get virtual function. When
the in function for an array or struct finds it is working
with a nil Lisp object, it can construct a representative
instance and fill in that one, then return it.
* ffi.c (struct txr_ffi_type): Change return type of in
function to val.
(ffi_freeing_in, ffi_ptr_in_in, ffi_ptr_out_in): Return type
changes to val, obj that is passed in is returned.
(ffi_struct_in): Return type changes to val. If the Lisp
structure passed in is nil, then construct a default instance
of the structure by invoking make_struct on the type, with no
arguments, and then operate on that structure. In either
case, return the structure.
(ffi_array_in): Similar change to ffi_struct_in. In the cases
when we are converting character arrays to strings, if the
Lisp object is nil, we just take the decoded string as
the array and return that. In the regular array case, we
check for the object being nil, and if so, construct an empty
vector in the right size, then fill it.
(make_ffi_type_pointer): in parameter's return type
changes to val.
|
|
|
|
|
|
| |
* ffi.c (ffi_type_lookup, ffi_init_extra_types): New
functions.
(ffi_init): Call ffi_init_extra_types.
|
|
|
|
|
|
|
|
|
| |
* ffi.c (ffi_type_compile): All cases where the syntax is an
atom just go through the ffi_typedef_hash lookup to retrieve a
single type instance.
(ffi_init_types): New function. Populates typedefs using
construction code that was previously in ffi_type_compile.
(ffi_init): Call ffi_init_types.
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Since we don't have the rtidx members in the txr_ffi_type
structure, there is no need to instantiate a type for
each element of an array. All elements can now share the
one type.
* ffi.c (ffi_array_in, ffi_array_put, ffi_array_out,
ffi_array_get, make_ffi_type_array): Refactor according to
tft->mtypes no longer being a list but a single type.
(ffi_type_compile): Do not recompile the syntax n times
for each element.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
We don't need type copying because the need for this
was driven by the rtvec implementation, which assigned
a unique rtidx to the nodes in a type tree, requiring
like types to be separately instantiated.
* ffi.c (struct txr_ffi_type): Remove member dup.
(ffi_struct_dup, ffi_ptr_dup): Function removed.
(make_ffi_type_builtin, make_ffi_type_struct,
make_ffi_type_array): Don't initialize dup.
(ffi_copy_type): Function removed.
(ffi_type_compile): don't call ffi_copy_type.
(ffi_init): ffi-copy-type intrinsic removed.
* ffi.h (ffi_copy_type): Declaration removed.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Remove features related to the supporting the removed
rtvec mechanism.
* ffi.c (struct txr_ffi_type): Member rtidx, rtsize and walk
removed.
(ffi_ptr_walk, ffi_struct_walk, ffi_type_walk,
assign_rtindices_visit, ffi_type_assign_rtindices,
ffi_compile_toplevel): Functions removed.
(make_ffi_type_pointer, make_ffi_type_struct,
make_ffi_type_array): Don't initialize rtsize and walk.
(ffi_type_compile): Don't initialize a type's rtsize.
(ffi_init): ffi-type-compile registereed to ffi_type_compile
rather than ffi_type_compile_toplevel, as was originally
the case.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Removing the rtvec[] mechanism for tracking temporary
allocations. The tft->in() calls are already walking the
object layout and so pointers can just be retrieved from the
object memory. This changes the semantics: for the better, I
think.
For example if a struct contains a (ptr str) and is passed as
(ptr (struct ...)), the C string is temporarily allocated and
stored in the C structure before the call, then freed after
the call. Now the freeing action retrieves the char * pointer
from the structure itself rather than rtvec. The semantics
change is that the pointer may have been altered by the C
function. We may be freeing a pointer other than the one we
allocated. C code which replaces the pointer must malloc it,
and free the original.
* ffi.c (struct txr_ffi_type): put and in virtual function
pointers lose the rtvec parameter.
(ffi_void_put ffi_i8_put, ffi_u8_put, ffi_i16_put,
ffi_u16_put, ffi_i32_put, ffi_u32_put, ffi_i64_put,
ffi_u64_put, ffi_char_put, ffi_uchar_put, ffi_short_put,
ffi_ushort_put, ffi_int_put, ffi_uint_put, ffi_long_put,
ffi_ulong_put, ffi_float_put, ffi_double_put, ffi_wchar_put,
ffi_cptr_put, ffi_str_d_put, ffi_wstr_put, ffi_wstr_d_put,
ffi_buf_put, ffi_buf_d_put, ffi_closure_put): Drop unused
rtvec parameter.
(freeing_in, ffi_ptr_in_in, ffi_ptr_out_in): Drop rtvec
parameter. Obtain pointer from src buffer instead.
(ffi_str_put, ffi_ptr_in_put, ffi_ptr_out_put, ffi_ptr_put):
Drop rtvec parameter and remove code which stored into rtvec.
(ffi_ptr_in_d_put, ffi_struct_put, ffi_array_put): Drop rtvec
parameter; don't pass to recursive put call.
(ffi_struct_in, ffi_array_in): Drop rtvec parameter; don't
pass to recursive in call.
(make_ffi_type_builtin, make_ffi_type_pointer): Adjust pointer
parameter declarators for put and in parameters.
(ffi_call_wrap): Remove allocation and use of rtvec.
Pass the values[i] pointer as the src parameter in the
to level in call.
(ffi_closure_dispatch): Don't pass rtvec parameter to
put call.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* ffi.c (ffi_void_put, ffi_fixed_alloc, ffi_noop_free,
ffi_void_get, ffi_i8_put, ffi_i8_get, ffi_u8_put, ffi_u8_get,
ffi_i16_put, ffi_i16_get, ffi_u16_put, ffi_u16_get,
ffi_i32_put, ffi_i32_get, ffi_u32_put, ffi_u32_get,
ffi_i64_put, ffi_i64_get, ffi_u64_put, ffi_u64_get,
ffi_char_put, ffi_char_get, ffi_uchar_put, ffi_uchar_get,
ffi_short_put, ffi_short_get, ffi_ushort_put, ffi_ushort_get,
ffi_int_put, ffi_int_get, ffi_uint_put, ffi_uint_get,
ffi_long_put, ffi_long_get, ffi_ulong_put, ffi_ulong_get,
ffi_float_put, ffi_float_get, ffi_double_put, ffi_double_get,
ffi_wchar_put, ffi_wchar_get, ffi_cptr_put, ffi_cptr_get,
ffi_cptr_alloc, ffi_freeing_in, ffi_str_d_put, ffi_str_get,
ffi_str_d_get, ffi_wstr_put, ffi_wstr_get, ffi_wstr_d_put,
ffi_wstr_d_get, ffi_buf_put, ffi_buf_get, ffi_buf_d_put,
ffi_buf_d_get, ffi_buf_alloc, ffi_ptr_in_d_put): Removed
void casts from these functions.
|
|
|
|
|
|
|
|
|
|
|
|
| |
* ffi.c (ffi_typedef_hash): New static variable.
(ffi_type_compile): Handle undefined atom case by trying
through typedef hash.
(ffi_typedef): New function.
(ffi_init): gc-protect ffi_type_compile variable and
initialize it with a hash table. Register ffi-typedef
intrinsic.
* ffi.h (ffi_typedef): Declared
|
|
|
|
|
|
|
|
|
|
|
|
| |
* ffi.c (struct txr_ffi_type): New member, dup.
(ffi_struct_dup, ffi_ptr_dup): New static functions.
(make_ffi_type_pointer, make_ffi_type_struct,
make_ffi_type_array): Set up dup virtual function for these
types.
(ffi_copy_type): New function.
(ffi_init): Register ffi-copy-type intrinsic.
* ffi.h (ffi_copy_type): Declared.
|
|
|
|
|
|
|
| |
* ffi.c (ffi_array_in): Support the char_conv and wchar_conv
flags similarly in ffi_array_get. This allows (ptr (array n
char)) to receive data from the C buffer as a string,
storing it into the string object.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
We need to extend the existing framework to handle the
requirement that the callback can update objects passed by
pointer, such that the changes are propagated to the original
C objects. For instance, a callback receives a pointer to a
struct with some strings. The Lisp code updates the strings
and we would like the strings to appear back in the C code.
The functions which support this sort of thing in the
call direction are not quite suitable for this purpose,
because that system relies on being able to nail temporary
buffers into a stack-allocated rtvec[] which is cleaned
up after the FFI call. Anything we write back to a C
structure in a FFI callback is is gone out the door; we
don't get to clean up any temporary malloced storage.
* ffi.c (struct txr_ffi_type): New member out: a virtual
fucnction which is like in, but in the opposite direction,
and not relying in rtvec. The copy flag argument
tells the function whether to just recurse, or whether
perform copying, or just recursion.
(ffi_ptr_in_out, ffi_ptr_out_out, ffi_struct_out,
ffi_array_out): New static functions.
(make_ffi_type_pointer): Take an a new parameter for
specifying out functions, and store it.
(make_ffi_type_struct): Set up an out handler for a struct
type or array which needs one. It is needed if any of the
element types have an out handler. Basic types don't have out
handlers; ptr types do. What if a struct is full of basic
types and has no out handler, and is the object of an out
pointer? In that case, the logic in ffi_ptr_out_out handles
it; it notices that its target type has no out handler, and
uses the struct's put function instead to update the
underlying C buffer.
(ffi_type_compile): Add in functions to ptr types.
(ffi_closure_dispatch): After calling the Lisp function,
perform a pass of out calls over the parameters, if
necessary.
|