summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2021-06-06 17:58:06 -0700
committerKaz Kylheku <kaz@kylheku.com>2021-06-06 17:58:06 -0700
commit16b390a2d811bb0dbe6f8d8bf1cf21cb397d3447 (patch)
treee8530efaca66c05d712f3238f9066fe4f31fd05f
parentdb161112abb1c684bf91b2c434e18b488c0aa2ca (diff)
downloadtxr-16b390a2d811bb0dbe6f8d8bf1cf21cb397d3447.tar.gz
txr-16b390a2d811bb0dbe6f8d8bf1cf21cb397d3447.tar.bz2
txr-16b390a2d811bb0dbe6f8d8bf1cf21cb397d3447.zip
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.
-rw-r--r--ffi.c11
-rw-r--r--txr.134
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