From 8d7fb1e9c023cec15bc5a843deeac1b6961b77ba Mon Sep 17 00:00:00 2001 From: Kaz Kylheku Date: Sun, 6 Jun 2021 17:58:06 -0700 Subject: ffi: allow conversion of carray objects under cptr. * ffi.c (ffi_cptr_put): If the object is not a cptr, try it as a carray. This requires the tft to have an eltype, requiring a change in ffi_type_compile. (ffi_type_compile): When compiling a parametrized cptr object, we now look up the type symbol as a FFI type, and store the result as the tft->eltype. If the symbol is not an FFI type, then this lookup returns nil. If the eltype is non-nil, then there is the possibility it can match the element type of a carray. * txr.1: Documented. --- ffi.c | 11 +++++++++-- txr.1 | 34 ++++++++++++++++++++++++++++++++-- 2 files changed, 41 insertions(+), 4 deletions(-) diff --git a/ffi.c b/ffi.c index 7c001187..9a104547 100644 --- a/ffi.c +++ b/ffi.c @@ -1901,10 +1901,16 @@ static val ffi_bool_rget(struct txr_ffi_type *tft, mem_t *src, val self) #endif -static void ffi_cptr_put(struct txr_ffi_type *tft, val n, mem_t *dst, +static void ffi_cptr_put(struct txr_ffi_type *tft, val ptr, mem_t *dst, val self) { - mem_t *p = cptr_handle(n, tft->tag, self); + mem_t *p = 0; + + if (type(ptr) == CPTR) + p = cptr_handle(ptr, tft->tag, self); + else + p = carray_ptr(ptr, tft->eltype, self); + *coerce(mem_t **, dst) = p; } @@ -3932,6 +3938,7 @@ val ffi_type_compile(val syntax) tft->alloc = ffi_cptr_alloc; tft->free = ffi_noop_free; tft->tag = tag; + tft->eltype = gethash(ffi_typedef_hash, tag); if (cddr(syntax)) goto excess; return type; diff --git a/txr.1 b/txr.1 index 72cff575..88bfebfe 100644 --- a/txr.1 +++ b/txr.1 @@ -74513,7 +74513,10 @@ type is similar to the unparametrized .codn cptr . It also converts between Lisp objects of type .code cptr -and foreign pointers. However, it provides a measure of type safety. +and foreign pointers. Unlike the unparametrized type, it provides a measure of +type safety, and also supports the conversion of +.code carray +objects. When a foreign pointer is converted to a Lisp object under control of the parametrized @@ -74544,7 +74547,34 @@ is specified as .codn nil , then this is precisely equivalent to the unparametrized .code cptr -which doesn't provides the above safety measure. +which doesn't provide the above safety measure. + +A +.code carray +object may also be converted to a foreign pointer under the control of +a parametrized +.code cptr +type. The +.code carray +object's internal pointer becomes the foreign pointer value. +The conversion is only permitted if the following two restrictions are not met, +otherwise an error exception is thrown. +Firstly, the +.meta type-sym +of the +.code cptr +type must be the name of an FFI type, at the time when the +.code cptr +type expression is processed, otherwise the +.code cptr +is not associated with a type. +Secondly, the +.code carray +object being converted must have an element type which matches the +FFI type denoted by the +.code cptr +object's +.metn type-sym . Pointer type safety is useful, because FFI can be used to create bindings to large application programming interfaces (APIs) in which objects of -- cgit v1.2.3