summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ffi.c35
-rw-r--r--txr.1131
2 files changed, 166 insertions, 0 deletions
diff --git a/ffi.c b/ffi.c
index 282aca78..1099f7fc 100644
--- a/ffi.c
+++ b/ffi.c
@@ -3670,6 +3670,15 @@ static val ffi_type_lookup(val sym)
return gethash(ffi_typedef_hash, sym);
}
+static val ffi_type_lookup_checked(val self, val sym)
+{
+ val type = gethash(ffi_typedef_hash, sym);
+ if (!type)
+ uw_throwf(error_s, lit("~a: unrecognized type specifier: ~s"),
+ self, sym, nao);
+ return type;
+}
+
static val ffi_struct_init(val slot_init, val strct)
{
val stype = struct_type(strct);
@@ -5947,6 +5956,30 @@ val fill_carray(val carray, val offs, val stream)
return ret;
}
+static val cptr_getobj(val cptr, val type_in)
+{
+ val self = lit("cptr-get");
+ mem_t *data = cptr_get(cptr);
+ val type = default_arg(type_in, ffi_type_lookup_checked(self, cptr->co.cls));
+ struct txr_ffi_type *tft = ffi_type_struct_checked(self, type);
+ if (data != 0)
+ return tft->get(tft, data, self);
+ uw_throwf(type_error_s, lit("~a: ~s is a null pointer"), self, cptr, nao);
+}
+
+static val cptr_out(val cptr, val obj, val type_in)
+{
+ val self = lit("cptr-out");
+ mem_t *data = cptr_get(cptr);
+ val type = default_arg(type_in, ffi_type_lookup_checked(self, cptr->co.cls));
+ struct txr_ffi_type *tft = ffi_type_struct_checked(self, type);
+ if (data != 0) {
+ tft->out(tft, 0, obj, data, self);
+ return obj;
+ }
+ uw_throwf(type_error_s, lit("~a: ~s is a null pointer"), self, cptr, nao);
+}
+
struct uni {
struct txr_ffi_type *tft;
mem_t *data;
@@ -6345,6 +6378,8 @@ void ffi_init(void)
}
reg_fun(intern(lit("put-carray"), user_package), func_n3o(put_carray, 1));
reg_fun(intern(lit("fill-carray"), user_package), func_n3o(fill_carray, 1));
+ reg_fun(intern(lit("cptr-get"), user_package), func_n2o(cptr_getobj, 1));
+ reg_fun(intern(lit("cptr-out"), user_package), func_n3o(cptr_out, 2));
reg_fun(intern(lit("make-union"), user_package), func_n3o(make_union, 1));
reg_fun(intern(lit("union-members"), user_package), func_n1(union_members));
reg_fun(intern(lit("union-get"), user_package), func_n2(union_get));
diff --git a/txr.1 b/txr.1
index ad04d24c..4bad3e2a 100644
--- a/txr.1
+++ b/txr.1
@@ -53452,6 +53452,137 @@ function retrieves the
.meta cptr
object's type tag.
+.coNP Function @ cptr-get
+.synb
+.mets (cptr-get < cptr <> [ type ])
+.syne
+.desc
+The
+.code cptr-get
+function extracts a Lisp value by converting a C object
+at the memory location denoted by
+.metn cptr ,
+according to the FFI type
+.metn type .
+The external representation at the specified memory location is
+is scanned according to the
+.meta type
+and converted to a Lisp value which is returned.
+
+If the
+.meta type
+argument is specified, it must be a FFI type object.
+If omitted, then the
+.code cptr
+object's type tag is interpreted as a FFI type symbol and resolved to
+a type; the resulting type, if one is found is substituted for
+.metn type .
+If the lookup fails an error exception is thrown.
+
+The
+.meta cptr
+object must be of type
+.code cptr
+and point to a memory area suitably aligned for, and large
+enough to hold a foreign representation of
+.metn type ,
+at the byte offset indicated by the
+.meta offset
+argument.
+
+If
+.meta cptr
+is a null pointer, an exception is thrown.
+
+The
+.code cptr-get
+operation is similar to the "get semantics" performed by FFI
+in order to extract the return value of foreign function
+calls, and by the FFI callback mechanism to extract the
+arguments coming into a callback.
+
+The
+.meta type
+argument may not be a variable length type, such as an array of
+unspecified size.
+
+Note: the
+.code cptr-get
+and
+.code cptr-out
+is useful in simplifying the interaction with "semi-opaque" foreign objects:
+objects which serve as a API handles that are treated as opaque pointers in API
+argument calls, but which expose some internal members that the application
+must access directly. The
+.code cptr
+objects pass through the foreign API without undergoing conversion,
+as usual. The application uses these two functions to perform conversion as
+necessary. Under this technique, the description of the foreign object need not
+be complete. Structure members which occur after the last member that the
+application is interested in need not be described in the FFI type.
+
+.coNP Function @ cptr-put
+.synb
+.mets (cptr-put < cptr < obj <> [ type ])
+.syne
+.desc
+The
+.code cptr-put
+function converts a Lisp value into a C representation,
+which is stored at the memory location denoted by
+.metn cptr ,
+according to the FFI type
+.metn type .
+The function's return value is
+.metn obj .
+
+If the
+.meta type
+argument is specified, it must be a FFI type object.
+If omitted, then the
+.code cptr
+object's type tag is interpreted as a FFI type symbol and resolved to
+a type; the resulting type, if one is found is substituted for
+.metn type .
+If the lookup fails an error exception is thrown.
+
+The
+.meta obj
+argument must be an object compatible with the conversions
+implied by
+.metn type .
+
+The
+.meta cptr
+object must be of type
+.code cptr
+and point to a memory area suitably aligned for, and large
+enough to hold a foreign representation of
+.metn type ,
+at the byte offset indicated by the
+.meta offset
+argument.
+
+If
+.meta cptr
+is a null pointer, an exception is thrown.
+
+It is assumed that
+.meta obj
+is an object which was returned by an earlier call to
+.codn cptr-get ,
+and that the
+.meta cptr
+and
+.meta type
+arguments are the same objects that were used in that call.
+
+The
+.code cptr-out
+function performs the "out semantics" encoding action, similar
+to the treatment applied to the arguments of a callback prior to
+returning to foreign code.
+
.coNP Variable @ cptr-null
.desc
The