guile-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Guile-commits] GNU Guile branch, master, updated. release_1-9-9-45-gb92


From: Andy Wingo
Subject: [Guile-commits] GNU Guile branch, master, updated. release_1-9-9-45-gb9264dc
Date: Tue, 06 Apr 2010 21:15:49 +0000

This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GNU Guile".

http://git.savannah.gnu.org/cgit/guile.git/commit/?id=b9264dc5f3c2c9341852b898bd3eb8587dbd20f3

The branch, master has been updated
       via  b9264dc5f3c2c9341852b898bd3eb8587dbd20f3 (commit)
      from  71725997c756e11e434983a8a19b4b205dc4265a (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit b9264dc5f3c2c9341852b898bd3eb8587dbd20f3
Author: Andy Wingo <address@hidden>
Date:   Tue Apr 6 23:17:10 2010 +0200

    finish ffi docs
    
    * libguile/foreign.c: Some doc tweaks.
    * doc/ref/api-foreign.texi: Finish FFI docs.

-----------------------------------------------------------------------

Summary of changes:
 doc/ref/api-foreign.texi |  277 ++++++++++++++++++++++++++++++++++------------
 libguile/foreign.c       |   20 +++-
 2 files changed, 222 insertions(+), 75 deletions(-)

diff --git a/doc/ref/api-foreign.texi b/doc/ref/api-foreign.texi
index 1e735db..2a4f0df 100644
--- a/doc/ref/api-foreign.texi
+++ b/doc/ref/api-foreign.texi
@@ -442,9 +442,10 @@ section takes up the problem of accessing C values from 
Scheme, and the
 next discusses C functions.
 
 @menu
-* Foreign Types::  foo
-* Foreign Variables::  foo
-* Foreign Pointers and Values::  foo
+* Foreign Types::                  Expressing C types in Scheme.
+* Foreign Variables::              Typed pointers.
+* Void Pointers and Byte Access::  Pointers into the ether.
+* Foreign Structs::                Packing and unpacking structs.
 @end menu
 
 @node Foreign Types
@@ -454,9 +455,9 @@ The first impedance mismatch that one sees between C and 
Scheme is that
 in C, the storage locations (variables) are typed, but in Scheme types
 are associated with values, not variables. @xref{Values and Variables}.
 
-So when accessing a C value from Scheme, we must give the type of the
-value explicitly, as a parameter to any procedure that translates
-between Scheme and C values.
+So when accessing a C value through a Scheme pointer, we must give the
+type of the pointed-to value explicitly, as a parameter to any Scheme
+procedure that accesses the value.
 
 These ``C type values'' may be constructed using the constants and
 procedures from the @code{(system foreign)} module, which may be loaded
@@ -469,9 +470,7 @@ like this:
 @code{(system foreign)} exports a number of values expressing the basic
 C types:
 
address@hidden {Scheme Variable} float
address@hidden {Scheme Variable} double
address@hidden {Scheme Variable} int8
address@hidden {Scheme Variable} int8
 @defvrx {Scheme Variable} uint8
 @defvrx {Scheme Variable} uint16
 @defvrx {Scheme Variable} int16
@@ -479,6 +478,8 @@ C types:
 @defvrx {Scheme Variable} int32
 @defvrx {Scheme Variable} uint64
 @defvrx {Scheme Variable} int64
address@hidden {Scheme Variable} float
address@hidden {Scheme Variable} double
 Values exported by the @code{(system foreign)} module, representing C
 numeric types of the specified sizes and signednesses.
 @end defvr
@@ -499,7 +500,7 @@ numeric types. For example, @code{long} may be 
@code{equal?} to
 @node Foreign Variables
 @subsubsection Foreign Variables
 
-Given the types defined in the previous section, foreign values may be
+Given the types defined in the previous section, C pointers may be
 looked up dynamically using @code{dynamic-pointer}.
 
 @deffn {Scheme Procedure} dynamic-pointer name type dobj [len]
@@ -529,12 +530,52 @@ numptob
 @result{} #<foreign int32 8>
 @end example
 
address@hidden
-This example shows that a @code{long} on this platform is an
address@hidden, and that the value pointed to by @code{numptob} is 8.
+A value returned by @code{dynamic-pointer} is a Scheme wrapper for a C
+pointer, with additional type information. A foreign pointer prints
+according to its type. This example showed that a @code{long} on this
+platform is an @code{int32}, and that the value pointed to by
address@hidden is 8.
+
+Typed pointers may be referenced using the @code{foreign-ref} and
address@hidden functions.
+
address@hidden {Scheme Procedure} foreign-ref foreign
address@hidden {C Function} scm_foreign_ref foreign
+Reference the foreign value pointed to by @var{foreign}.
+
+The value will be referenced according to its type.
+
address@hidden
+(foreign-ref numptob) @result{} 8 ; YMMV
address@hidden example
address@hidden deffn
+
address@hidden {Scheme Procedure} foreign-set! foreign val
address@hidden {C Function} scm_foreign_set_x foreign val
+Set the foreign value pointed to by @var{foreign}.
+
+The value will be set according to its type.
+
address@hidden
+(foreign-set! numptob 120) ; Don't try this at home!
address@hidden example
address@hidden deffn
+
+If we wanted to corrupt Guile's internal state, we could set
address@hidden to another value; but we shouldn't, because that
+variable is not meant to be set. Indeed this point applies more widely:
+the C API is a dangerous place to be. Not only might setting a value
+crash your program, simply referencing a value with a wrong-sized type
+can prove equally disastrous.
 
address@hidden Foreign Pointers and Values
address@hidden Foreign Pointers and Values
+
address@hidden Void Pointers and Byte Access
address@hidden Void Pointers and Byte Access
+
+As a special case, a dynamic pointer may be declared to point to type
address@hidden, in which case it is treated as a void pointer. A void
+pointer prints its value as a pointer, without dereferencing the
+pointer.
 
 It's important at this point to conceptually separate foreign values
 from foreign pointers. @code{dynamic-pointer} gives you a foreign
@@ -553,8 +594,12 @@ Guile can wrap such a pointer, by declaring that it points 
to
 @code{void}.
 
 @defvr {Scheme Variable} void
-A C type, used when wrapping C pointers. @code{void} represents the type
-to which the pointer points.
+A foreign type value representing nothing.
+
address@hidden has two uses: for a foreign pointer, declaring it to be of
+type @code{void} is like having a @code{void*} in C. For a function, a
+return type of @code{void} indicates that the function returns no
+values. A function argument type of @code{void} is invalid.
 @end defvr
 
 As an example, @code{(dynamic-pointer "foo" void bar-lib)} links in the
@@ -588,44 +633,83 @@ Mutating the returned bytevector mutates the memory 
pointed to by
 @var{foreign}, so buckle your seatbelts.
 @end deffn
 
address@hidden {Scheme Procedure} foreign-set! foreign val
address@hidden {C Function} scm_foreign_set_x foreign val
-Set the foreign value wrapped by @var{foreign}.
address@hidden {Scheme Procedure} bytevector->foreign bv [offset [len]]
address@hidden {C Function} scm_bytevector_to_foreign bv offset len
+Return a foreign pointer aliasing the memory pointed to by
address@hidden
 
-The value will be set according to its type.
+The resulting foreign will be a void pointer, a foreign whose
+type is @code{void}. By default it will alias all of the
+memory pointed to by @var{bv}, from beginning to end.
+
+Users may explicily specify that the foreign should only alias a
+subset of the memory, by specifying @var{offset} and @var{len}
+arguments.
 @end deffn
 
-Typed pointers may be referenced using the @code{foreign-ref} and
address@hidden functions.
 
address@hidden {Scheme Procedure} foreign-ref foreign
address@hidden {C Function} scm_foreign_ref foreign
-Reference the foreign value wrapped by @var{foreign}.
address@hidden Foreign Structs
address@hidden Foreign Structs
 
-The value will be referenced according to its type.
+Finally, one last note on foreign values before moving on to actually
+calling foreign functions. Sometimes you need to deal with C structs,
+which requires interpreting each element of the struct according to the
+its type, offset, and alignment. Guile has some primitives to support
+this.
+
address@hidden {Scheme Procedure} sizeof type
address@hidden {C Function} scm_sizeof type
+Return the size of @var{type}, in bytes.
+
address@hidden should be a valid C type, like @code{int}.
+Alternately @var{type} may be the symbol @code{*}, in which
+case the size of a pointer is returned. @var{type} may
+also be a list of types, in which case the size of a
address@hidden with ABI-conventional packing is returned.
address@hidden deffn
 
address@hidden
-(foreign-ref numptob) @result{} 8 ; YMMV
address@hidden example
address@hidden {Scheme Procedure} alignof type
address@hidden {C Function} scm_alignof type
+Return the alignment of @var{type}, in bytes.
+
address@hidden should be a valid C type, like @code{int}.
+Alternately @var{type} may be the symbol @code{*}, in which
+case the alignment of a pointer is returned. @var{type} may
+also be a list of types, in which case the alignment of a
address@hidden with ABI-conventional packing is returned.
 @end deffn
 
address@hidden {Scheme Procedure} foreign-set! foreign val
address@hidden {C Function} scm_foreign_set_x foreign val
-Set the foreign value wrapped by @var{foreign}.
+Guile also provides some convenience methods to pack and unpack foreign
+pointers wrapping C structs.
 
-The value will be set according to its type.
address@hidden {Scheme Procedure} make-c-struct types vals
+Create a foreign pointer to a C struct containing @var{vals} with types
address@hidden
+
address@hidden and @code{types} should be lists of the same length.
address@hidden deffn
+
address@hidden {Scheme Procedure} parse-c-struct foreign types
+Parse a foreign pointer to a C struct, returning a list of values.
+
address@hidden should be a list of C types.
address@hidden deffn
+
+For example, to create and parse the equivalent of a @code{struct @{
+int64_t a; uint8_t b; @}}:
 
 @example
-(foreign-set! numptob 120) ; Don't try this at home!
+(parse-c-struct (make-c-struct (list int64 uint8)
+                               (list 300 43))
+                (list int64 uint8))
address@hidden (300 43)
 @end example
address@hidden deffn
 
-If we wanted to corrupt Guile's internal state, we could set
address@hidden to another value; but we shouldn't, because that
-variable is not meant to be set. Indeed this point applies more widely:
-the C API is a dangerous place to be. Not only might setting a value
-crash your program, simply referencing a value with a wrong-sized type
-can prove equally disastrous.
+As yet, Guile only has convenience routines to support
+conventionally-packed structs. But given the @code{bytevector->foreign}
+and @code{foreign->bytevector} routines, one can create and parse
+tightly packed structs and unions by hand. See the code for
address@hidden(system foreign)} for details.
 
 
 @node Dynamic FFI
@@ -644,52 +728,103 @@ procedure that will pass arguments to the foreign 
function
 and return appropriate values.
 
 @var{arg_types} should be a list of foreign types.
address@hidden should be a foreign type.
address@hidden should be a foreign type. @xref{Foreign Types}, for
+more information on foreign types.
 @end deffn
 
-TBD
+Here is a better definition of @code{(math bessel)}:
 
address@hidden
-* Foreign Structs::
address@hidden menu
address@hidden
+(define-module (math bessel)
+  #:use-module (system foreign)
+  #:export (j0))
 
+(define libm (dynamic-link "libm"))
 
address@hidden Foreign Structs
address@hidden Foreign Structs
+(define j0
+  (make-foreign-function double
+                         (dynamic-func "j0" libm)
+                         (list double)))
address@hidden example
 
-Compared to Scheme, C is a lower-level language, but it does have the
-ability to compose types into structs and unions, so Guile must support
-these as well.
+That's it! No C at all.
 
-Oftentimes one only accesses structures through pointers. In that case,
-it's easy to use void pointers and the bytevector interface to access
-structures. However C allows functions to accept and return structures
-and unions by value, on the stack, so it's necessary to be able to
-express structure and union types as Scheme values.
+Numeric arguments and return values from foreign functions are
+represented as Scheme values. For example, @code{j0} in the above
+example takes a Scheme number as its argument, and returns a Scheme
+number.
 
-Conventionally-packed st
+Pointers may be passed to and returned from foreign functions as well.
+In that case the type of the argument or return value should be the
+symbol @code{*}, indicating a pointer. For example, the following
+code makes @code{memcpy} available to Scheme:
 
-As yet, Guile only has support for conventionally-packed structs.
-tightly-packed structs and unions will
address@hidden
+(define memcpy
+  (let ((this (dynamic-link)))
+    (make-foreign-function '*
+                           (dynamic-func "memcpy" this)
+                           (list '* '* size_t))))
address@hidden example
+
+To invoke @code{memcpy}, one must pass it foreign pointers:
+
address@hidden
+(use-modules (rnrs bytevector))
 
-Note that the Scheme values for C types are just that, @emph{values},
-not names. @code{(quote int64 uint8)} won't do what you want.
+(define src
+  (bytevector->foreign (u8-list->bytevector '(0 1 2 3 4 5 6 7))))
+(define dest
+  (bytevector->foreign (make-bytevector 16 0)))
 
-C does not only have numeric types; one other type that it has is the
address@hidden, which in Guile is represented as a list of C types, so
-that the following two type declarations are equivalent:
+(memcpy dest src (bytevector-length (foreign->bytevector src)))))
+
+(bytevector->u8-list (foreign->bytevector dest))
address@hidden (0 1 2 3 4 5 6 7 0 0 0 0 0 0 0 0)
address@hidden example
+
+One may also pass structs as values, passing structs as foreign
+pointers. @xref{Foreign Structs}, for more information on how to express
+struct types and struct values.
+
+``Out'' arguments are passed as foreign pointers. The memory pointed to
+by the foreign pointer is mutated in place.
 
 @example
-struct @{ int64_t foo; uint8_t bar; @}
-(list int64 uint8)
+;; struct timeval @{
+;;      time_t      tv_sec;     /* seconds */
+;;      suseconds_t tv_usec;    /* microseconds */
+;; @};
+;; assuming fields are of type "long"
+
+(define gettimeofday
+  (let ((f (make-foreign-function
+            int
+            (dynamic-func "gettimeofday" (dynamic-link))
+            (list '* '*)))
+        (tv-type (list long long)))
+    (lambda ()
+      (let* ((timeval (make-c-struct tv-type (list 0 0)))
+             (ret (f timeval %null-pointer)))
+        (if (zero? ret)
+            (apply values (parse-c-struct timeval tv-type))
+            (error "gettimeofday returned an error" ret))))))
+
+(gettimeofday)    
address@hidden 1270587589
address@hidden 499553
 @end example
 
-Putting Scheme types in a list is the same as declaring a struct type
-with the default packing. Guile does not currently support
-tightly-packed structs; in that case you should declare the value as
-being a void pointer, and access the bytes as a bytevector.
+This example also shows use of @code{%null-pointer}, which is a null
+foreign pointer, exported by @code{(system foreign)}.
 
address@hidden {Scheme Variable} %null-pointer
+A foreign pointer whose value is 0.
address@hidden defvr
 
+As you can see, this interface to foreign functions is at a very low,
+somewhat dangerous level. A contribution to Guile in the form of a
+high-level FFI would be most welcome.
 
 @c Local Variables:
 @c TeX-master: "guile.texi"
diff --git a/libguile/foreign.c b/libguile/foreign.c
index 06be7a5..9f307ef 100644
--- a/libguile/foreign.c
+++ b/libguile/foreign.c
@@ -112,7 +112,7 @@ scm_take_foreign_pointer (scm_t_foreign_type type, void 
*ptr, size_t len,
 
 SCM_DEFINE (scm_foreign_ref, "foreign-ref", 1, 0, 0,
            (SCM foreign),
-           "Reference the foreign value wrapped by @var{foreign}.\n\n"
+           "Reference the foreign value pointed to by @var{foreign}.\n\n"
             "The value will be referenced according to its type.")
 #define FUNC_NAME s_scm_foreign_ref
 {
@@ -157,7 +157,7 @@ SCM_DEFINE (scm_foreign_ref, "foreign-ref", 1, 0, 0,
 
 SCM_DEFINE (scm_foreign_set_x, "foreign-set!", 2, 0, 0,
            (SCM foreign, SCM val),
-           "Set the foreign value wrapped by @var{foreign}.\n\n"
+           "Set the foreign value pointed to by @var{foreign}.\n\n"
             "The value will be set according to its type.")
 #define FUNC_NAME s_scm_foreign_set_x
 {
@@ -426,7 +426,13 @@ scm_i_foreign_print (SCM foreign, SCM port, 
scm_print_state *pstate)
 
 #define ROUND_UP(len,align) (align?(((len-1)|(align-1))+1):len)
 
-SCM_DEFINE (scm_alignof, "alignof", 1, 0, 0, (SCM type), "")
+SCM_DEFINE (scm_alignof, "alignof", 1, 0, 0, (SCM type),
+            "Return the alignment of @var{type}, in bytes.\n\n"
+            "@var{type} should be a valid C type, like @code{int}.\n"
+            "Alternately @var{type} may be the symbol @code{*}, in which\n"
+            "case the alignment of a pointer is returned. @var{type} may\n"
+            "also be a list of types, in which case the alignment of a\n"
+            "@code{struct} with ABI-conventional packing is returned.")
 #define FUNC_NAME s_scm_alignof
 {
   if (SCM_I_INUMP (type))
@@ -468,7 +474,13 @@ SCM_DEFINE (scm_alignof, "alignof", 1, 0, 0, (SCM type), 
"")
 }
 #undef FUNC_NAME
 
-SCM_DEFINE (scm_sizeof, "sizeof", 1, 0, 0, (SCM type), "")
+SCM_DEFINE (scm_sizeof, "sizeof", 1, 0, 0, (SCM type),
+            "Return the size of @var{type}, in bytes.\n\n"
+            "@var{type} should be a valid C type, like @code{int}.\n"
+            "Alternately @var{type} may be the symbol @code{*}, in which\n"
+            "case the size of a pointer is returned. @var{type} may also\n"
+            "be a list of types, in which case the size of a @code{struct}\n"
+            "with ABI-conventional packing is returned.")
 #define FUNC_NAME s_scm_sizeof
 {
   if (SCM_I_INUMP (type))


hooks/post-receive
-- 
GNU Guile




reply via email to

[Prev in Thread] Current Thread [Next in Thread]