diff options
author | Ludovic Courtès <ludo@gnu.org> | 2011-01-30 22:00:35 +0100 |
---|---|---|
committer | Ludovic Courtès <ludo@gnu.org> | 2011-01-30 23:29:29 +0100 |
commit | 1f4f7674bc352be9c5bdce0e0fb346345b04fa81 (patch) | |
tree | eb2b02c60b12c0e5c13ea4ef85170060c196b7d5 /doc/ref/api-foreign.texi | |
parent | 2519490c50ae063ef27201c5403e80628fff9eeb (diff) | |
download | guile-1f4f7674bc352be9c5bdce0e0fb346345b04fa81.tar.gz |
Add `define-wrapped-pointer-type'.
* module/system/foreign.scm (define-wrapped-pointer-type): New macro.
* doc/ref/api-foreign.texi (Foreign Types): Mention the `*' symbol.
(Void Pointers and Byte Access): Document `define-wrapped-pointer-type'.
* test-suite/tests/foreign.test ("define-wrapped-pointer-type"): New
test prefix.
Diffstat (limited to 'doc/ref/api-foreign.texi')
-rw-r--r-- | doc/ref/api-foreign.texi | 74 |
1 files changed, 72 insertions, 2 deletions
diff --git a/doc/ref/api-foreign.texi b/doc/ref/api-foreign.texi index 69a10933f..9b9e481dc 100644 --- a/doc/ref/api-foreign.texi +++ b/doc/ref/api-foreign.texi @@ -1,7 +1,7 @@ @c -*-texinfo-*- @c This is part of the GNU Guile Reference Manual. -@c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004, 2007, 2008, 2009, 2010 -@c Free Software Foundation, Inc. +@c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004, 2007, 2008, +@c 2009, 2010, 2011 Free Software Foundation, Inc. @c See the file guile.texi for copying conditions. @node Foreign Function Interface @@ -495,6 +495,10 @@ The @code{void} type. It can be used as the first argument to @code{pointer->procedure} to wrap a C function that returns nothing. @end defvr +In addition, the symbol @code{*} is used by convention to denote pointer +types. Procedures detailed in the following sections, such as +@code{pointer->procedure}, accept it as a type descriptor. + @node Foreign Variables @subsubsection Foreign Variables @@ -613,6 +617,72 @@ in the current locale encoding. This is the Scheme equivalent of @code{scm_from_locale_string}. @end deffn +@cindex wrapped pointer types +Most object-oriented C libraries use pointers to specific data +structures to identify objects. It is useful in such cases to reify the +different pointer types as disjoint Scheme types. The +@code{define-wrapped-pointer-type} macro simplifies this. + +@deffn {Scheme Syntax} define-wrapped-pointer-type pred wrap unwrap print +Define helper procedures to wrap pointer objects into Scheme objects +with a disjoint type. Specifically, this macro defines: + +@itemize +@item @var{pred}, a predicate for the new Scheme type; +@item @var{wrap}, a procedure that takes a pointer object and returns an +object that satisfies @var{pred}; +@item @var{unwrap}, which does the reverse. +@end itemize + +@var{wrap} preserves pointer identity, for two pointer objects @var{p1} +and @var{p2} that are @code{equal?}, @code{(eq? (@var{wrap} @var{p1}) +(@var{wrap} @var{p2})) @result{} #t}. + +Finally, @var{print} should name a user-defined procedure to print such +objects. The procedure is passed the wrapped object and a port to write +to. + +For example, assume we are wrapping a C library that defines a type, +@code{bottle_t}, and functions that can be passed @code{bottle_t *} +pointers to manipulate them. We could write: + +@example +(define-wrapped-pointer-type bottle? + wrap-bottle unwrap-bottle + (lambda (b p) + (format p "#<bottle of ~a ~x>" + (bottle-contents b) + (pointer-address (unwrap-foo b))))) + +(define grab-bottle + ;; Wrapper for `bottle_t *grab (void)'. + (let ((grab (pointer->procedure '* + (dynamic-func "grab_bottle" libbottle) + '()))) + (lambda () + "Return a new bottle." + (wrap-bottle (grab))))) + +(define bottle-contents + ;; Wrapper for `const char *bottle_contents (bottle_t *)'. + (let ((contents (pointer->procedure '* + (dynamic-func "bottle_contents" + libbottle) + '(*)))) + (lambda (b) + "Return the contents of B." + (pointer->string (contents (unwrap-bottle b)))))) + +(write (grab-bottle)) +@result{} #<bottle of Ch@^ateau Haut-Brion 803d36> +@end example + +In this example, @code{grab-bottle} is guaranteed to return a genuine +@code{bottle} object satisfying @code{bottle?}. Likewise, +@code{bottle-contents} errors out when its argument is not a genuine +@code{bottle} object. +@end deffn + Going back to the @code{scm_numptob} example above, here is how we can read its value as a C @code{long} integer: |