[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH 18/25] write documentation for (system foreign declarative)
From: |
KAction |
Subject: |
[PATCH 18/25] write documentation for (system foreign declarative) |
Date: |
Mon, 18 Jul 2016 18:17:41 +0300 |
From: Dmitry Bogatov <address@hidden>
Document '<foreign-type>' record type and 'define-foreign-type' procedure.
---
doc/ref/api-foreign.texi | 150 ++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 147 insertions(+), 3 deletions(-)
diff --git a/doc/ref/api-foreign.texi b/doc/ref/api-foreign.texi
index c2c49ec..605dbed 100644
--- a/doc/ref/api-foreign.texi
+++ b/doc/ref/api-foreign.texi
@@ -26,6 +26,7 @@ procedures.
* Modules and Extensions:: Loading C extensions into modules.
* Foreign Pointers:: Accessing global variables.
* Dynamic FFI:: Calling arbitrary C functions.
+* Declarative dynamic FFI:: Declarative macros for calling C functions
@end menu
@@ -439,10 +440,10 @@ section takes up the problem of accessing C values from
Scheme, and the
next discusses C functions.
@menu
-* Foreign Types:: Expressing C types in Scheme.
-* Foreign Variables:: Pointers to C symbols.
+* Foreign Types:: Expressing C types in Scheme.
+* Foreign Variables:: Pointers to C symbols.
* Void Pointers and Byte Access:: Pointers into the ether.
-* Foreign Structs:: Packing and unpacking structs.
+* Foreign Structs:: Packing and unpacking structs.
@end menu
@node Foreign Types
@@ -980,6 +981,149 @@ on a few exotic architectures. Thus, user code may need
to check
many architectures, including (as of libffi 3.0.9) x86, ia64, SPARC,
PowerPC, ARM, and MIPS, to name a few.
address@hidden Declarative dynamic FFI
address@hidden Declarative dynamic FFI
+
+Dynamic foreign function interface, described in previous section is
+powerful and sufficient to bind power of almost any C library to Guile
+with only Scheme code. But it is very low-level and does not provide any
+abstractions for common function conventions. This is where module
address@hidden(system foreign declarative)} comes into the game.
+
address@hidden {Record type} <foreign-type> name validate encode decode type
address@hidden<foreign-type>} record represents correspondence between C data
+type and some Scheme object. It contains @code{name} for purposes of
+error reporting, procedure @code{validate}, which will can be called
+with single argument and return @code{#t} if it's argument is suitable
+for passing to @code{encode} procedure, and return @code{#f} or throw if
+not.
+
+Procedure @code{encode} converts Scheme object of arbitrary complexity
+to C data type, coherent to @code{type}. @xref{Dynamic FFI} Procedure
address@hidden converts back from C data type to some Scheme object.
+At least one of them should be present for record be useful.
+
+Fields of @code{<foreign-type>} record must (but not enforced)
+to obey following rules:
+
address@hidden
+
address@hidden
+Every procedure @code{validate}, @code{encode} and @code{decode} are
+pure -- their result depends only on argument, and they do nothing,
+except of returning a value.
address@hidden
+;; for every `procedure' from 'validate', 'encode', 'decode'
+;; for every Scheme value `x'
+;; following expressions are either both throw or return same value.
+;; they can freely be replaced one with another.
+(list (procedure x)
+ (procedure x))
+(let ((value (validate x))
+ (list value value)))
address@hidden example
+
address@hidden
+If field @code{decode} is present, procedure @code{decode} accepts any
+argument with type matching @code{type} field and returns normally some
+value. If both @code{decode} and @code{encode} fields are present,
+value, returned by @code{decode} procedure, can be encoded back by
address@hidden procedure.
address@hidden
+;; For every Scheme value 'x', matching field 'type' following expression
+;; never throw and always evaluates to #t
+(equal? (encode (decode x)) x)
address@hidden example
+
address@hidden
+For every value, for which @code{validate} procedure returned @code{#t},
address@hidden procedure returns normally.
address@hidden
+;; For every Scheme value 'x' following expression never throws
+(and (false-if-exception (validate x))
+ (encode x))
address@hidden example
address@hidden enumerate
address@hidden deftp
+
address@hidden {Scheme Macro} define-foreign-type name @
+ [#:validate-proc=(const #t)] @
+ [#:encode-proc=error] @
+ [#:decode-proc=error] @
+ [#:type='*]
+Defines @code{name} to a @code{<foreign-type>} record with @code{name},
+fields @code{validate-proc}, @code{encode-proc}, @code{decode-proc},
address@hidden configured with keywords arguments.
+
+Here is how one may define foreign type record, that match C integer with
+Scheme boolean
address@hidden
+(use-modules (system foreign)) ;; `int' is defined there
+(use-modules (system foreign declarative))
+
+(define (boolean->integer b)
+ (if b 1 0))
+(define (integer->boolean i)
+ (not (zero? i))
+
+(define-foreign-type boolean:
+ #:validate-proc boolean?
+ #:encode-proc boolean->integer
+ #:decode-proc integer->boolean
+ #:type int)
address@hidden example
+By convention, @code{<foreign-type>} record's names ends with colon.
address@hidden deffn
+
+Module @code{(system foreign declarative)} provides such records for
+every primitive C type exported by @code{(system foreign)}.
+
address@hidden {Scheme Macro} define-foreign-function function-name ((type
name) ...) :: return @
+ [#:dynamic-library=(dynamic-link)] [#:symbol]
+Define Scheme procedure @code{function-name}, that wraps C function with name
@code{symbol}
+from dynamic library @code{dynamic-library}. Both @code{return} and
@code{type} arguments
+must be @code{<foreign-type>} records, to specify how to pass arguments to
underlying
+C function.
+
+Arguments, passed to @code{function-name} are validated and encoded
+according to specified @code{type}s, passed to C function. Return value
+of C function is decoded according to @code{return} foreign-type record.
+
address@hidden is name of C function, unless specified explicitly is deduced
+from @code{function-name} by following rules:
+
address@hidden
+
address@hidden
+Remove prefix "c-" prefix, if present.
address@hidden
+Replace every non-alphanumeric symbol with underscores.
+
address@hidden enumerate
+
+Here are some examples of @code{define-foreign-function} usage:
address@hidden
+;; In such simple case neither 'dynamic-library' keyword needed, since
+;; 'sin' function is already in library, pulled by libguile, neither
+;; 'symbol' keyword, since underlying function name "sin" is deduced
+(define-foreign-function c-sin ((double: arg)) :: double:)
+(equal? (c-sin 10) (sin 10)) ; #t
+
+;; In case of time(3) function, we must specify correct signature,
+;; but we can %null-pointer and hide implementation details.
+(define ask-time
+ (let ()
+ (define-foreign-function c-time ((*: t)) :: long:)
+ (lambda ()
+ (c-time %null-pointer))))
+
+(ask-time) ; 1468434734, at time of writing
+
+;; We can as easily work with constant strings
+(define-foreign-time c-rename ((string: oldpath) (string: newpath)) :: int:)
address@hidden example
address@hidden deffn
+
@c Local Variables:
@c TeX-master: "guile.texi"
@c End:
--
I may be not subscribed. Please, keep me in carbon copy.
- [PATCH 08/25] Add keywords for `define-foreign-function' macro, (continued)
- [PATCH 08/25] Add keywords for `define-foreign-function' macro, KAction, 2016/07/18
- [PATCH 10/25] Refactor type validation in `define-foreign-function', KAction, 2016/07/18
- [PATCH 09/25] system/foreign/declarative: rename `predicate' to `validate', KAction, 2016/07/18
- [PATCH 11/25] system/foreign/declarative: new macro, KAction, 2016/07/18
- [PATCH 13/25] system/foreign/declarative.scm: export string foreign type, KAction, 2016/07/18
- [PATCH 12/25] Improve deriving c symbol name from scheme one, KAction, 2016/07/18
- [PATCH 14/25] foreign/declarative: mirror more primitive types, KAction, 2016/07/18
- [PATCH 15/25] New macro: with-pointer, KAction, 2016/07/18
- [PATCH 16/25] Configure emacs file-local indention, KAction, 2016/07/18
- [PATCH 17/25] system/foreign/declarative: unexport internal macro, KAction, 2016/07/18
- [PATCH 18/25] write documentation for (system foreign declarative),
KAction <=
[PATCH 20/25] Document with-pointer macro, KAction, 2016/07/18
[PATCH 19/25] Document define-foreign-bitmask macro, KAction, 2016/07/18
[PATCH 21/25] new module: (ice-9 xattr), KAction, 2016/07/18
[PATCH 22/25] ice-9/xattr: implement `xattr-get' function, KAction, 2016/07/18
[PATCH 24/25] Refactor defining foreign libattr function, KAction, 2016/07/18
[PATCH 25/25] ice9/attr: implement xattr-list procedure, KAction, 2016/07/18