mirror of
git://git.code.sf.net/p/sbcl/sbcl
synced 2026-09-10 07:26:40 -04:00
259 lines
8.9 KiB
Plaintext
259 lines
8.9 KiB
Plaintext
@c Generated by the sb-manual contrib. Do not edit.
|
|
|
|
@node sb grovel
|
|
@section sb-grovel
|
|
|
|
@menu
|
|
* Using sb-grovel in your own ASDF System: using sb grovel.
|
|
* Contents of a grovel-constants-file: sb grovel constants file.
|
|
* Programming with sb-grovel's structure types: sb grovel structures.
|
|
* Traps and Pitfalls: sb grovel traps.
|
|
@end menu
|
|
|
|
The @code{sb-grovel} module helps in generation of foreign function
|
|
interfaces. It aids in extracting constants' values from the C
|
|
compiler and in generating sb-alien structure and union types,
|
|
@ref{defining foreign types}.
|
|
|
|
The ASDF (@url{http://www.cliki.net/ASDF}) component type
|
|
GROVEL-CONSTANTS-FILE has its @code{asdf:perform} operation defined to
|
|
write out a C source file, compile it, and run it. The output from
|
|
this program is Lisp, which is then itself compiled and loaded.
|
|
|
|
@code{sb-grovel} is used in a few contributed modules, and it is
|
|
currently compatible only to SBCL. However, if you want to use it,
|
|
here are a few directions.
|
|
|
|
@node using sb grovel
|
|
@subsection Using sb-grovel in your own ASDF System
|
|
|
|
@itemize
|
|
@item Create a Lisp package for the foreign constants/functions to go
|
|
@end itemize
|
|
into.
|
|
|
|
@itemize
|
|
@item Make your system depend on the @code{sb-grovel} system.
|
|
|
|
@item Create a grovel-constants data file -- for an example, see
|
|
@code{example-constants.lisp} in the @code{contrib/sb-grovel/} directory in
|
|
the SBCL source distribution.
|
|
|
|
@item Add it as a component in your system. For example:
|
|
|
|
@example
|
|
(eval-when (:compile-toplevel :load-toplevel :execute)
|
|
(require :sb-grovel))
|
|
|
|
(defpackage :example-package.system
|
|
(:use :cl :asdf :sb-grovel :sb-alien))
|
|
|
|
(in-package :example-package.system)
|
|
|
|
(defsystem example-system
|
|
:depends-on (sb-grovel)
|
|
:components
|
|
((:module "sbcl"
|
|
:components
|
|
((:file "defpackage")
|
|
(grovel-constants-file "example-constants"
|
|
:package :example-package)))))
|
|
@end example
|
|
@end itemize
|
|
|
|
Make sure to specify the package you chose in step 1.
|
|
|
|
@itemize
|
|
@item Build stuff.
|
|
@end itemize
|
|
|
|
@node sb grovel constants file
|
|
@subsection Contents of a grovel-constants-file
|
|
|
|
The grovel-constants-file, typically named @code{constants.lisp},
|
|
comprises lisp expressions describing the foreign things that you
|
|
want to grovel for. A @code{constants.lisp} file contains two sections:
|
|
|
|
@itemize
|
|
@item a list of headers to include in the C program, for example:
|
|
|
|
@example
|
|
("sys/types.h" "sys/socket.h" "sys/stat.h" "unistd.h" "sys/un.h"
|
|
"netinet/in.h" "netinet/in_systm.h" "netinet/ip.h" "net/if.h"
|
|
"netdb.h" "errno.h" "netinet/tcp.h" "fcntl.h" "signal.h")
|
|
@end example
|
|
|
|
@item A list of sb-grovel clauses describing the things you want to
|
|
grovel from the C compiler, for example:
|
|
|
|
@example
|
|
((:integer af-local
|
|
#+(or sunos solaris) "AF_UNIX"
|
|
#-(or sunos solaris) "AF_LOCAL"
|
|
"Local to host (pipes and file-domain).")
|
|
(:structure stat ("struct stat"
|
|
(integer dev "dev_t" "st_dev")
|
|
(integer atime "time_t" "st_atime")))
|
|
(:function getpid ("getpid" int )))
|
|
@end example
|
|
@end itemize
|
|
|
|
There are two types of things that sb-grovel can sensibly extract
|
|
from the C compiler: constant integers and structure layouts. It is
|
|
also possible to define foreign functions in the constants.lisp
|
|
file, but these definitions don't use any information from the C
|
|
program; they expand directly to @code{sb-alien:define-alien-routine}
|
|
forms.
|
|
|
|
Here's how to use the grovel clauses:
|
|
|
|
@itemize
|
|
@item @code{:integer}: constant expressions in C. Used in this form:
|
|
|
|
@example
|
|
(:integer lisp-variable-name "C expression" &optional doc export)
|
|
@end example
|
|
|
|
@code{"C expression"} will be typically be the name of a constant,
|
|
but other forms are possible.
|
|
|
|
@item @code{:enum}:
|
|
|
|
@example
|
|
(:enum lisp-type-name ((lisp-enumerated-name c-enumerated-name) ...)))
|
|
@end example
|
|
|
|
An @code{sb-alien:enum} type with name @code{lisp-type-name} will be
|
|
defined. The symbols are the @code{lisp-enumerated-name}s, and the
|
|
values are grovelled from the @code{c-enumerated-name}s.
|
|
|
|
@item @code{:structure}: alien structure definitions look like this:
|
|
|
|
@example
|
|
(:structure lisp-struct-name ("struct c_structure"
|
|
(type-designator lisp-element-name
|
|
"c_element_type" "c_element_name"
|
|
:distrust-length nil)
|
|
; ...
|
|
))
|
|
@end example
|
|
|
|
@code{type-designator} is a reference to a type whose size (and type
|
|
constraints) will be groveled for. sb-grovel accepts a form of
|
|
type designator that doesn't quite conform to either lisp nor
|
|
sb-alien's type specifiers. Here's a list of type designators
|
|
that sb-grovel currently accepts:
|
|
|
|
@itemize
|
|
@item @code{integer}: a C integral type; sb-grovel will infer the exact
|
|
type from size information extracted from the C program. All
|
|
common C integer types can be grovelled for with this type
|
|
designator, but it is not possible to grovel for bit fields
|
|
yet.
|
|
|
|
@item @code{(unsigned n)}: an unsigned integer variable that is @code{n} bytes
|
|
long. No size information from the C program will be used.
|
|
|
|
@item @code{(signed n)}: an signed integer variable that is @code{n} bytes
|
|
long. No size information from the C program will be used.
|
|
|
|
@item @code{c-string}: an array of @code{char} in the structure. sb-grovel
|
|
will use the array's length from the C program, unless you
|
|
pass it the @code{:distrust-length} keyword argument with non-@code{nil}
|
|
value (this might be required for structures such as solaris's
|
|
@code{struct dirent}).
|
|
|
|
@item @code{sb-grovel::c-string-pointer}: a pointer to a C string,
|
|
corresponding to the @code{sb-alien:c-string} type (see
|
|
@ref{foreign type specifiers}).
|
|
|
|
@item @code{(array alien-type)}: an array of the previously-declared
|
|
@code{alien-type}. The array's size will be determined from the
|
|
output of the C program and the alien type's size.
|
|
|
|
@item @code{(array alien-type n):} an array of the previously-declared
|
|
@code{alien-type}. The array's size will be assumed as being @code{n}.
|
|
@end itemize
|
|
@end itemize
|
|
|
|
Note that @code{c-string} and @code{sb-grovel::c-string-pointer} do not have
|
|
the same meaning. If you declare that an element is of type
|
|
@code{c-string}, it will be treated as if the string is a part of the
|
|
structure, whereas if you declare that the element is of type
|
|
@code{sb-grovel::c-string-pointer}, a @emph{pointer to a string} will be the
|
|
structure member.
|
|
|
|
@itemize
|
|
@item @code{:function}: alien function definitions are similar to
|
|
@code{define-alien-routine} definitions, because they expand to such
|
|
forms when the lisp program is loaded. See
|
|
@ref{foreign function calls}.
|
|
|
|
@example
|
|
(:function lisp-function-name
|
|
("alien_function_name" alien-return-type
|
|
(argument alien-type)
|
|
(argument2 alien-type)))
|
|
@end example
|
|
@end itemize
|
|
|
|
@node sb grovel structures
|
|
@subsection Programming with sb-grovel's structure types
|
|
|
|
Let us assume that you have a grovelled structure definition:
|
|
|
|
@example
|
|
(:structure mystruct ("struct my_structure"
|
|
(integer myint "int" "st_int")
|
|
(c-string mystring "char[]" "st_str")))
|
|
@end example
|
|
|
|
What can you do with it? Here's a short interface document:
|
|
|
|
@itemize
|
|
@item Creating and destroying objects:
|
|
|
|
@itemize
|
|
@item Function @code{(allocate-mystruct)} allocates an object of type
|
|
@code{mystruct} and returns a system area pointer to it.
|
|
|
|
@item Macro @code{(with-mystruct var ((member init) [...]) &body body)}
|
|
allocates an object of type @code{mystruct} that is valid in
|
|
@code{body}. If @code{body} terminates or performs an non-local exit,
|
|
the object pointed to by @code{var} will be deallocated.
|
|
@end itemize
|
|
|
|
@item Accessing structure members:
|
|
|
|
@itemize
|
|
@item @code{(mystruct-myint var)} and @code{(mystruct-mystring var)} return
|
|
the value of the respective fields in @code{mystruct}.
|
|
|
|
@item @code{(setf (mystruct-myint var) new-val)} and
|
|
@code{(setf (mystruct-mystring var) new-val)} sets the value of the
|
|
respective structure member to the value of @code{new-val}. Notice
|
|
that in @code{(setf (mystruct-mystring var) new-val)}'s case,
|
|
@code{new-val} is a lisp string.
|
|
@end itemize
|
|
@end itemize
|
|
|
|
@node sb grovel traps
|
|
@subsection Traps and Pitfalls
|
|
|
|
Basically, you can treat functions and data structure definitions that
|
|
sb-grovel spits out as if they were alien routines and types. This has
|
|
a few implications that might not be immediately obvious (especially
|
|
if you have programmed in a previous version of sb-grovel that didn't
|
|
use alien types):
|
|
|
|
@itemize
|
|
@item You must take care of grovel-allocated structures yourself. They
|
|
are alien types, so the garbage collector will not collect them
|
|
when you drop the last reference.
|
|
|
|
@item If you use the @code{with-mystruct} macro, be sure that no references
|
|
to the variable thus allocated leaks out. It will be deallocated
|
|
when the block exits.
|
|
@end itemize
|
|
|