summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2017-05-20 16:58:34 -0700
committerKaz Kylheku <kaz@kylheku.com>2017-05-20 16:58:34 -0700
commita7517ded29c1c3bf8a50b2ce690bcfac575db350 (patch)
tree5223e5bde27713fa354f4a07f69c610b8de1e224
parent765548d93ca58734805e2932565398fe31d5a517 (diff)
downloadtxr-a7517ded29c1c3bf8a50b2ce690bcfac575db350.tar.gz
txr-a7517ded29c1c3bf8a50b2ce690bcfac575db350.tar.bz2
txr-a7517ded29c1c3bf8a50b2ce690bcfac575db350.zip
ffi: new macro, deffi-var.
* lisplib.c (ffi_set_entries): Autload entry for "deffi-var". * share/txr/stdlib/ffi.tl (deffi-var): New macro. * txr.1: Documented.
-rw-r--r--lisplib.c3
-rw-r--r--share/txr/stdlib/ffi.tl15
-rw-r--r--txr.144
3 files changed, 61 insertions, 1 deletions
diff --git a/lisplib.c b/lisplib.c
index acc7b6b6..df5e9a93 100644
--- a/lisplib.c
+++ b/lisplib.c
@@ -524,7 +524,8 @@ static val ffi_set_entries(val dlt, val fun)
{
val name[] = {
lit("with-dyn-lib"), lit("deffi"), lit("deffi-type"), lit("deffi-cb"),
- lit("typedef"), lit("sizeof"), lit("ffi"), lit("carray-ref"),
+ lit("deffi-var"), lit("typedef"), lit("sizeof"), lit("ffi"),
+ lit("carray-ref"),
nil
};
set_dlt_entries(dlt, name, fun);
diff --git a/share/txr/stdlib/ffi.tl b/share/txr/stdlib/ffi.tl
index ce497d17..69a19a1e 100644
--- a/share/txr/stdlib/ffi.tl
+++ b/share/txr/stdlib/ffi.tl
@@ -96,6 +96,21 @@
(defmacro deffi-cb-unsafe (:form f name rettype argtypes)
(sys:deffi-cb-expander f name rettype argtypes nil nil))
+(defmacro deffi-var (:form f name var-expr type)
+ (let ((var-ref (cond
+ ((stringp var-expr)
+ ^(dlsym-checked sys:ffi-lib ,var-expr))
+ ((consp var-expr)
+ (mac-param-bind f (sym ver) var-expr
+ ^(dlvsym-checked sys:ffi-lib ,sym ,ver)))
+ (t var-expr)))
+ (type-sym (gensym "type-"))
+ (var-sym (gensym "var-")))
+ ^(progn
+ (defvarl ,type-sym (ffi ,type))
+ (defvarl ,var-sym (carray-cptr ,var-ref ,type-sym 1))
+ (defsymacro ,name (carray-ref ,var-sym 0)))))
+
(defmacro sizeof (type)
(ffi-size (ffi-type-compile type)))
diff --git a/txr.1 b/txr.1
index 99f3599b..423fdb8e 100644
--- a/txr.1
+++ b/txr.1
@@ -54686,6 +54686,50 @@ parameter, since unsafe callbacks do not use it.
.cble
+.coNP Macro @ deffi-var
+.synb
+.mets (deffi-var < name < var-expr << type )
+.syne
+.desc
+The
+.code deffi-var
+macro defines a global symbol macro which expands to an expression
+accessing a foreign variable, creating the illusion that the
+variable is available as a Lisp variable holding a Lisp data type.
+
+The
+.meta name
+argument gives the name of the macro.
+
+The
+.meta var-expr
+argument must evaluate to a
+.code cptr
+object which holds a pointer to the address of the foreign
+variable.
+
+The
+.meta type
+argument expresses the variable type in FFI type syntax.
+
+Once the variable is defined, accessing the macro symbol
+.meta name
+performs a get operation on the foreign variable, yielding
+the conversion of that variable to a Lisp value.
+An assignment to the symbol performs a put operation,
+converting a Lisp object to a value which overwrites
+the object.
+
+Note: FFI memory management is not helpful in the use of
+variables. Suppose a string value is
+stored in a variable of type
+.codn str .
+This means that FFI dynamically allocates a buffer which
+stores the UTF-8 encoded version of the string, and this
+buffer is placed into the foreign variable.
+Then suppose another such assignment takes place.
+The previous value is simply overwritten without being
+freed.
.coNP Macro @ typedef
.synb
.mets (typedef < name << type-syntax )