summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2017-06-19 23:21:41 -0700
committerKaz Kylheku <kaz@kylheku.com>2017-06-19 23:21:41 -0700
commit1ebafaf91f4f2bb09a1f4d23d7bfcfa97506a0e8 (patch)
tree686dd3007265a9e16a122521e3b18e6351006944
parent9dbcde8882a8a917b6d0329e06ea2232e62b1c8c (diff)
downloadtxr-1ebafaf91f4f2bb09a1f4d23d7bfcfa97506a0e8.tar.gz
txr-1ebafaf91f4f2bb09a1f4d23d7bfcfa97506a0e8.tar.bz2
txr-1ebafaf91f4f2bb09a1f4d23d7bfcfa97506a0e8.zip
cptr-int and cptr-obj can make typed cptr objects.
* eval.c (eval_init): Update registration of cptr-int and cptr-obj with one optional argument. * lib.c (cptr_int): New type symbol argument, defaulting to nil. Also, don't bother defaulting the integer argument; the function isn't registered for that being optional. (cptr_obj): New type symbol argument, defaulting to nil. * lib.h (cptr_int, cptr_obj): Declarations updated. * txr.1: Documented cptr-int and cptr-obj function changes. Added discussion of type tag to introductory paragraph. Also added neglected documentation of the FFI cptr type, both unparametrized and parametrized.
-rw-r--r--eval.c4
-rw-r--r--lib.c10
-rw-r--r--lib.h4
-rw-r--r--txr.1116
4 files changed, 123 insertions, 11 deletions
diff --git a/eval.c b/eval.c
index d1c3cc8c..46c9bb72 100644
--- a/eval.c
+++ b/eval.c
@@ -6157,8 +6157,8 @@ void eval_init(void)
reg_fun(intern(lit("rlcp"), user_package), func_n2(rlcp));
reg_fun(intern(lit("rlcp-tree"), user_package), func_n2(rlcp_tree));
- reg_fun(intern(lit("cptr-int"), user_package), func_n1(cptr_int));
- reg_fun(intern(lit("cptr-obj"), user_package), func_n1(cptr_obj));
+ reg_fun(intern(lit("cptr-int"), user_package), func_n2o(cptr_int, 1));
+ reg_fun(intern(lit("cptr-obj"), user_package), func_n2o(cptr_obj, 1));
reg_fun(intern(lit("cptr-zap"), user_package), func_n1(cptr_zap));
reg_fun(intern(lit("cptr-free"), user_package), func_n1(cptr_free));
reg_fun(intern(lit("cptrp"), user_package), func_n1(cptrp));
diff --git a/lib.c b/lib.c
index bf51d9df..80d056b4 100644
--- a/lib.c
+++ b/lib.c
@@ -7531,14 +7531,16 @@ val cptr_type(val cptr)
return cptr->co.cls;
}
-val cptr_int(val n)
+val cptr_int(val n, val type_sym_in)
{
- return if3(missingp(n), cptr(0), cptr(coerce(mem_t *, c_num(n))));
+ val type_sym = default_null_arg(type_sym_in);
+ return cptr_typed(coerce(mem_t *, c_num(n)), type_sym, 0);
}
-val cptr_obj(val obj)
+val cptr_obj(val obj, val type_sym_in)
{
- return cptr(coerce(mem_t *, obj));
+ val type_sym = default_null_arg(type_sym_in);
+ return cptr_typed(coerce(mem_t *, obj), type_sym, 0);
}
val cptr_zap(val cptr)
diff --git a/lib.h b/lib.h
index 24db79f1..ffe10c84 100644
--- a/lib.h
+++ b/lib.h
@@ -957,8 +957,8 @@ val cptr(mem_t *ptr);
val cptr_typed(mem_t *handle, val type_sym, struct cobj_ops *ops);
val cptrp(val obj);
val cptr_type(val cptr);
-val cptr_int(val n);
-val cptr_obj(val obj);
+val cptr_int(val n, val type_sym);
+val cptr_obj(val obj, val type_sym);
val cptr_zap(val cptr);
val cptr_free(val cptr);
mem_t *cptr_get(val cptr);
diff --git a/txr.1 b/txr.1
index a0cbd8e8..14c60d98 100644
--- a/txr.1
+++ b/txr.1
@@ -53584,11 +53584,32 @@ function and is generally useful in conjunction with the Foreign Function
Interface (FFI). An arbitrary pointer emanating from a foreign function
can be captured as a
.code cptr
-value, which can be passed back into foreign code.
+value, which can be passed back into foreign code. For this purpose, there
+exits also a matching FFI type called
+.codn cptr .
+
+The
+.code cptr
+type supports a symbolic type tag, which defaults to
+.codn nil .
+The type tag plays a role in FFI. The FFI
+.code cptr
+type supports a tag attribute. When a
+.code cptr
+object is converted to a foreign pointer under the control of the FFI
+type, an that FFI type has a tag other than
+.codn nil ,
+the object's tag must exactly match that of the FFI type, or the conversion
+throws an error. In the reverse direction, when a foreign pointer is
+converted to a
+.code cptr
+object under control of the FFI
+.code cptr
+type, the object inherits the type tag from the FFI type.
.coNP Function @ cptr-int
.synb
-.mets (cptr-int << integer )
+.mets (cptr-int < integer <> [ type-symbol ])
.syne
.desc
The
@@ -53610,9 +53631,17 @@ range; a portion of the range of
.code bignum
integers can denote pointers.
+The
+.meta type-symbol
+argument should be a symbol. If omitted, it defaults to
+.codn nil .
+This symbol becomes the
+.code cptr
+object's type tag.
+
.coNP Function @ cptr-obj
.synb
-.mets (cptr-int << object )
+.mets (cptr-int < object <> [ type-symbol ])
.syne
.desc
The
@@ -53632,6 +53661,14 @@ is simply stored in a new instance of
.code cptr
and returned.
+The
+.meta type-symbol
+argument should be a symbol. If omitted, it defaults to
+.codn nil .
+This symbol becomes the
+.code cptr
+object's type tag.
+
.coNP Function @ cptr-zap
.synb
.mets (cptr-zap << cptr )
@@ -54289,6 +54326,34 @@ macro. The
type is useful for passing callbacks to foreign functions: Lisp functions
which appear to be C functions to foreign code.
+.ccIP @ cptr
+The
+.code cptr
+type converts between a foreign pointer and a Lisp object of type
+.codn cptr .
+
+Lisp objects of type
+.code cptr
+are tagged with a symbolic tag, which may be
+.codn nil .
+
+The unparametrized
+.code cptr
+converts foreign pointers to
+.code cptr
+objects which are tagged with
+.codn nil .
+
+In the reverse direction, it converts
+.code cptr
+Lisp objects of type
+.code cptr
+to foreign pointer, without regard for their type tag.
+
+There is a parametrized version of the
+.code cptr
+FFI type, which provides a measure of type safety.
+
.ccIP @ void
The
.code void
@@ -55052,6 +55117,51 @@ It is possible to create a
view over a buffer, using
.codn carray-buf .
+.meIP (cptr << type-sym )
+The parametrized
+.code cptr
+type is very 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.
+
+When a foreign pointer is converted to a Lisp object under control of the
+parametrized
+.codn cptr ,
+the resulting Lisp
+.code cptr
+object is tagged with the
+.meta type-sym
+symbol.
+
+In the reverse direction, when a Lisp
+.code cptr
+object is converted to the parametrized type, its type tag must match
+.metn type-sym ,
+or else the conversion fails with an error exception.
+
+Note that if
+.meta type-sym
+is specified as
+.codn nil ,
+then this is precisely equivalent to the unparametrized
+.code cptr
+which doesn't provides the above safety measure.
+
+Pointer type safety is useful, because FFI can be used to create bindings
+to large application programming interfaces (APIs) in which objects of
+many different kinds are referenced using pointer handles. The erroneous
+situation can occur that a FFI call passes a handle of one kind to a function
+expecting a different kind of handle. If all pointer handles are represented
+by a single
+.code cptr
+type, then such a situation proceeds without diagnosis.
+If handles of different types are all mapped to
+.code cptr
+types with different tags, the situation is intercepted and diagnosed
+with an error exception.
+
.meIP (align < width << type )
The FFI type operator
.code align