X-Git-Url: http://repo.macrolet.net/gitweb/?a=blobdiff_plain;ds=inline;f=doc%2Fffi.sgml;h=5f11eabebbebd742da6ad968749112bbb18fc586;hb=57500f8641535b9b958abe1e8b65863941becf4f;hp=498fd1900b5ea5b870b0e88d8b3cb1e3d8ddc3ee;hpb=6139c89c89f45c03509e4f3156293ff656716a8c;p=sbcl.git
diff --git a/doc/ffi.sgml b/doc/ffi.sgml
index 498fd19..5f11eab 100644
--- a/doc/ffi.sgml
+++ b/doc/ffi.sgml
@@ -1,35 +1,1231 @@
The Foreign Function Interface>
-FIXME: The material in the &CMUCL; manual about the foreign
-function interface should be reviewed, reformatted in DocBook,
-lightly edited for &SBCL;, and substituted into this manual. But in
-the meantime, the original &CMUCL; manual is still 95+% correct for
-the &SBCL; version of the foreign function interface. (The main
-difference is that the package names have changed. CMU CL's FFI
-is in two packages named ALIEN>> and
-C-CALL>>. The corresponding SBCL FFI is
-in a single package named
-SB-ALIEN>>.)
-
-
-
-See the sections
+This chapter describes &SBCL;'s interface to C programs and
+libraries (and, since C interfaces are a sort of lingua
+franca> of the Unix world, to other programs and libraries in
+general.)
+
+In the modern Lisp world, the usual term for this
+functionality is Foreign Function Interface, or FFI>, where
+despite the mention of function> in this term, FFI> also
+refers to direct manipulation of C data structures as well as
+functions. The traditional &CMUCL; terminology is Alien Interface, and
+while that older terminology is no longer used much in the system
+documentation, it still reflected in names in the
+implementation, notably in the name of the SB-ALIEN>
+package.
+
+Introduction to the Foreign Function Interface>
+
+
+
+Because of Lisp's emphasis on dynamic memory allocation and garbage
+collection, Lisp implementations use non-C-like memory representations
+for objects. This representation mismatch creates friction when a Lisp
+program must share objects with programs which expect C data. There
+are three common approaches to establishing communication:
+
+ The burden can be placed on the foreign program
+ (and programmer) by requiring the knowledge and use of the
+ representations used internally by the Lisp implementation.
+ This can require a considerable amount of glue> code on the
+ C side, and that code tends to be sensitively dependent on the
+ internal implementation details of the Lisp system.
+ The Lisp system can automatically convert objects
+ back and forth between the Lisp and foreign representations.
+ This is convenient, but translation becomes prohibitively slow
+ when large or complex data structures must be shared. This approach
+ is supported by the &SBCL; FFI>, and used automatically
+ by the when passing integers and strings.
+ The Lisp program can directly manipulate foreign
+ objects through the use of extensions to the Lisp language.
+
+
+
+&SBCL;, like &CMUCL; before it, relies primarily on the
+automatic conversion and direct manipulation approaches. The SB-ALIEN
+package provices a facility wherein foreign values of simple scalar
+types are automatically converted and complex types are directly
+manipulated in their foreign representation. Additionally the
+lower-level System Area Pointers (or SAPs) can be used where
+necessary to provide untyped access to foreign memory.
+
+Any foreign objects that can't automatically be converted into
+Lisp values are represented by objects of type alien-value>.
+Since Lisp is a dynamically typed language, even foreign objects must
+have a run-time type; this type information is provided by
+encapsulating the raw pointer to the foreign data within an
+alien-value> object.
+
+The type language and operations on foreign types are
+intentionally similar to those of the C language.
+
+
+
+Foreign Types>
+
+
+Alien types have a description language based on nested list
+structure. For example the C type
+struct foo {
+ int a;
+ struct foo *b[100];
+};
+has the corresponding &SBCL; FFI type
+(struct foo
+ (a int)
+ (b (array (* (struct foo)) 100)))
+
+
+Defining Foreign Types>
+
+
+Types may be either named or anonymous. With structure and union
+types, the name is part of the type specifier, allowing recursively
+defined types such as:
+(struct foo (a (* (struct foo))))
+An anonymous structure or union type is specified by using the name
+nil>. The with-alien> macro defines a local
+scope which captures> any named type definitions. Other types
+are not inherently named, but can be given named abbreviations using
+the define-alien-type> macro.
+
+
+
+
+Foreign Types and Lisp Types>
+
+
+The foreign types form a subsystem of the &SBCL; type system. An
+alien> type specifier provides a way to use any foreign type as a
+Lisp type specifier. For example,
+(typep foo '(alien (* int)))
+can be used to determine whether foo> is a pointer to a foreign
+int>. alien> type specifiers can be used in the same ways
+as ordinary Lisp type specifiers (like string>.) Alien type
+declarations are subject to the same
+precise type checking
+as any other declaration.
+
+
+
+Note that the type identifiers used in the
+foreign type system overlap with native Lisp type
+specifiers in some cases. For example, the type specifier
+(alien single-float) is identical to single-float>, since
+foreign floats are automatically converted to Lisp floats. When
+type-of> is called on an alien value that is not automatically
+converted to a Lisp value, then it will return an alien> type
+specifier.
+
+
+
+
+Foreign Type Specifiers>
+
+
+All foreign type names are exported from the sb-alien>
+package. Some foreign type names are also symbols in
+the common-lisp> package, in which case they are
+reexported from the sb-alien> package, so that
+e.g. it is legal to refer to sb-alien:single-float>.
+
+
+
+These are the basic foreign type specifiers:
+
+
+
+
+ The foreign type specifier (* foo)> describes a
+ pointer to an object of type foo>. A pointed-to type
+ foo> of t> indicates a pointer to anything,
+ similar to void *> in ANSI C. A null alien pointer can
+ be detected with the sb-alien:null-alien>
+ function.
+
+
+
+
+ The foreign type specifier (array foo &optional dimensions)>
+ describes array of the specified dimensions>, holding
+ elements of type foo>. Note that (unlike in C) (* foo)>
+ (array foo)}> are considered to be different types when
+ type checking is done. If equivalence of pointer and array types
+ is desired, it may be explicitly coerced using
+ sb-alien:cast>.
+
+
+ Arrays are accessed using sb-alien:deref>, passing
+ the indices as additional arguments. Elements are stored in
+ column-major order (as in C), so the first dimension determines
+ only the size of the memory block, and not the layout of the
+ higher dimensions. An array whose first dimension is variable
+ may be specified by using nil> as the first dimension.
+ Fixed-size arrays can be allocated as array elements, structure
+ slots or sb-alien:with-alien> variables. Dynamic
+ arrays can only be allocated using sb-alien:make-alien>.
+
+
+
+
+ The foreign type specifier
+ (sb-alien:struct name &rest fields)>
+ describes a structure type with the specified name> and
+ fields>. Fields are allocated at the same offsets
+ used by the implementation's C compiler. If name>
+ is nil> then the structure is anonymous.
+
+
+ If a named foreign struct> specifier is passed to
+ define-alien-type> or with-alien>,
+ then this defines, respectively, a new global or local foreign
+ structure type. If no fields> are specified, then
+ the fields are taken from the current (local or global) alien
+ structure type definition of name>.
+
+
+
+
+ The foreign type specifier
+ (sb-alien:union name &rest fields)>
+ is similar to sb-alien:struct>, but describes a union type.
+ All fields are allocated at the same offset, and the size of the
+ union is the size of the largest field. The programmer must
+ determine which field is active from context.
+
+
+
+
+ The foreign type specifier (sb-alien:enum name &rest specs)>
+ describes an enumeration type that maps between integer values
+ and keywords. If name> is nil>, then the
+ type is anonymous. Each element of the specs>
+ list is either a Lisp keyword, or a list (keyword value)>.
+ value> is an integer. If value> is not
+ supplied, then it defaults to one greater than the value for
+ the preceding spec (or to zero if it is the first spec.)
+
+
+
+
+ The foreign type specifier (sb-alien:signed &optional bits)>
+ specifies a signed integer with the specified number of
+ bits> precision. The upper limit on integer
+ precision is determined by the machine's word
+ size. If bits> is not specified, the maximum
+ size will be used.
+
+
+
+
+ The foreign type specifier (integer &optional bits)> is
+ equivalent to the corresponding type specifier using
+ sb-alien:signed> instead of integer>.
+
+
+
+
+ The foreign type specifier
+ (sb-alien:unsigned &optional bits)>
+ is like corresponding type specifier using sb-alien:signed>
+ except that the variable is treated as an unsigned integer.
+
+
+
+
+ The foreign type specifier (boolean &optional bits)> is
+ similar to an enumeration type, but maps from Lisp nil>
+ and t> to C 0> and 1>
+ respectively. bits> determines the amount of
+ storage allocated to hold the truth value.
+
+
+
+
+ The foreign type specifier single-float> describes a
+ floating-point number in IEEE single-precision format.
+
+
+
+
+ The foreign type specifier double-float> describes a
+ floating-point number in IEEE double-precision format.
+
+
+
+
+ The foreign type specifier
+ (function result-type &rest arg-types)>
+ describes a foreign function that takes arguments of the specified
+ arg-types> and returns a result of type result-type>.
+ Note that the only context where a foreign function> type
+ is directly specified is in the argument to
+ sb-alien:alien-funcall>.
+ In all other contexts, foreign functions are represented by
+ foreign function pointer types: (* (function ...))>.
+
+
+
+
+ The foreign type specifier sb-alien:system-area-pointer>
+ describes a pointer which is represented in Lisp as a
+ system-area-pointer> object. &SBCL; exports this type from
+ sb-alien> because &CMUCL; did, but tentatively (as of
+ the first draft of this section of the manual, &SBCL; 0.7.6) it is
+ deprecated, since it doesn't seem to be required by user code.
+
+
+
+
+ The foreign type specifier sb-alien:void> is
+ used in function types to declare that no useful value
+ is returned. Using alien-funcall>
+ to call a void> foreign function will return
+ zero values.
+
+
+
+
+ The foreign type specifier sb-alien:c-string>
+ is similar to (* char)>, but is interpreted as a
+ null-terminated string, and is automatically converted into a
+ Lisp string when accessed; or if the pointer is C NULL>
+ or 0>, then accessing it gives Lisp nil>.
+ Lisp strings are stored with a trailing NUL termination, so no
+ copying (either by the user or the implementation) is necessary
+ when passing them to foreign code.
+
+
+ Assigning a Lisp string to a c-string> structure field or
+ variable stores the contents of the string to the memory already
+ pointed to by that variable. When a foreign object of type
+ (* char)> is assigned to a c-string>, then the
+ c-string> pointer is assigned to. This allows
+ c-string> pointers to be initialized. For example:
+ (cl:in-package "CL-USER") ; which USEs package "SB-ALIEN"
+ (define-alien-type nil (struct foo (str c-string)))
+ (defun make-foo (str) (let ((my-foo (make-alien (struct foo))))
+ (setf (slot my-foo 'str) (make-alien char (length str))
+ (slot my-foo 'str) str) my-foo))
+ Storing Lisp NIL> in a c-string> writes C
+ NULL> to the variable.
+
+
+
+
+ sb-alien> also exports translations of these C type
+ specifiers as foreign type specifiers:
+ sb-alien:char>,
+ sb-alien:short>,
+ sb-alien:int>,
+ sb-alien:long>,
+ sb-alien:unsigned-char>,
+ sb-alien:unsigned-short>,
+ sb-alien:unsigned-int>,
+ sb-alien:unsigned-long>,
+ sb-alien:float>, and
+ sb-alien:double>.
+
+
+
+
+
+
+
+Operations On Foreign Values>
+
+
+This section describes how to read foreign values as Lisp
+values, how to coerce foreign values to different kinds of foreign values, and
+how to dynamically allocate and free foreign variables.
+
+Accessing Foreign Values>
+
+(sb-alien:deref pointer-or-array &rest indices)>
+
+The sb-alien:deref> function returns the value pointed to by
+a foreign pointer, or the value of a foreign array element. When
+dereferencing a pointer, an optional single index can be specified to
+give the equivalent of C pointer arithmetic; this index is scaled by
+the size of the type pointed to. When dereferencing an array, the
+number of indices must be the same as the number of dimensions in the
+array type. deref> can be set with setf> to
+assign a new value.
+
+(sb-alien:slot struct-or-union &rest slot-names)>
+
+The sb-alien:slot> function extracts the value of
+the slot named slot-name> from a foreign struct> or
+union>. If struct-or-union> is a pointer to a
+structure or union, then it is automatically dereferenced.
+sb-alien:slot> can be set with setf> to assign
+a new value. Note that slot-name> is evaluated, and need
+not be a compile-time constant (but only constant slot accesses are
+efficiently compiled.)
+
+Untyped memory>
+
+As noted at the beginning of the chapter, the System Area
+Pointer facilities allow untyped access to foreign memory. SAPs can
+be converted to and from the usual typed foreign values using
+sap-alien and alien-sap
+(described elsewhere), and also to and from integers - raw machine
+addresses. They should thus be used with caution; corrupting the Lisp
+heap or other memory with SAPs is trivial.
+
+(sb-sys:int-sap machine-address)>
+
+Creates a SAP pointing at the virtual address
+machine-address.
+
+(sb-sys:sap-ref-32 sap offset)>
+
+Access the value of the memory location at
+offset bytes from sap. This form
+may also be used with setf to alter the memory at
+that location.
+
+(sb-sys:sap= sap1 sap2)>
+
+Compare sap1 and sap2 for
+equality.
+
+Similarly named functions exist for accessing other sizes of
+word, other comparisons, and other conversions. The reader is invited
+to use apropos and describe
+for more details
+
+(apropos "sap" :sb-sys)
+
+
+
+Coercing Foreign Values>
+
+(sb-alien:addr alien-expr)>
+
+
+The sb-alien:addr> macro
+returns a pointer to the location specified by
+alien-expr>, which must be either a foreign variable, a use of
+sb-alien:deref>, a use of sb-alien:slot>, or a use of
+sb-alien:extern-alien>.
+
+
+(sb-alien:cast foreign-value new-type)>
+
+The sb-alien:cast>
+converts foreign-value> to a new foreign value with the specified
+new-type>. Both types, old and new, must be foreign pointer,
+array or function types. Note that the resulting Lisp
+foreign variable object
+is not eq> to the
+argument, but it does refer to the same foreign data bits.
+
+(sb-alien:sap-alien sap type)>
+
+The sb-alien:sap-alien> function converts sap>
+(a system area pointer) to a foreign value with the specified
+type>. type> is not evaluated.
+
+
+The type> must be some foreign pointer, array, or
+record type.
+
+(sb-alien:alien-sap foreign-value type)>
+
+The sb-alien:alien-sap> function
+returns the SAP which points to alien-value>'s data.
+
+
+The foreign-value> must be of some foreign pointer,
+array, or record type.
+
+
+
+Foreign Dynamic Allocation>
+
+Lisp code can call the C standard library functions
+malloc> and free> to dynamically allocate and
+deallocate foreign variables. The Lisp code shares the same allocator
+with foreign C code, so it's OK for foreign code to call
+free> on the result of Lisp
+sb-alien:make-alien>, or for Lisp code to call
+sb-alien:free-alien> on foreign objects allocated by C
+code.
+
+(sb-alien:make-alien type size)>
+
+The sb-alien:make-alien> macro
+returns a dynamically allocated foreign value of the specified
+type> (which is not evaluated.) The allocated memory is not
+initialized, and may contain arbitrary junk. If supplied,
+size> is an expression to evaluate to compute the size of the
+allocated object. There are two major cases:
+
+
+ When type> is a foreign array type, an array of
+ that type is allocated and a pointer to it is returned. Note that you
+ must use deref> to change the result to an array before you
+ can use deref> to read or write elements:
+
+ (cl:in-package "CL-USER") ; which USEs package "SB-ALIEN"
+ (defvar *foo* (make-alien (array char 10)))
+ (type-of *foo*) => (alien (* (array (signed 8) 10)))
+ (setf (deref (deref foo) 0) 10) => 10
+ If supplied, size> is used as the first dimension for the
+ array.
+
+
+ When type> is any other foreign type, then an
+ object for that type is allocated, and a pointer to it is
+ returned. So (make-alien int)> returns a (* int)>.
+ If size> is specified, then a block of that many
+ objects is allocated, with the result pointing to the first one.
+
+
+
+
+(sb-alien:free-alien foreign-value)>
+
+The sb-alien:free-alien> function
+frees the storage for foreign-value>,
+which must have been allocated with Lisp make-alien>
+or C malloc>.
+
+See also the sb-alien:with-alien> macro, which
+allocates foreign values on the stack.
+
+
+
+Foreign Variables>
+
+
+
+Both local (stack allocated) and external (C global) foreign variables are
+supported.
+
+
+Local Foreign Variables>
+
+(sb-alien:with-alien var-definitions &body body)>
+
+The with-alien>
+macro establishes local
+foreign variables
+with the specified
+alien types and names.
+This form is analogous to defining a local variable in C: additional
+storage is allocated, and the initial value is copied.
+This form is less
+analogous to LET-allocated Lisp variables, since the variables
+can't be captured in closures: they live only for the dynamic extent
+of the body, and referring to them outside is a gruesome error.
+
+
+The var-definitions> argument is a list of
+variable definitions, each of the form
+(name type &optional initial-value)
+The names of the variables are established as symbol-macros; the bindings have
+lexical scope, and may be assigned with setq>
+or setf>.
+
+
+The with-alien> macro also establishes
+a new scope for named structures
+and unions. Any type> specified for a variable may contain
+named structure or union types with the slots specified. Within the
+lexical scope of the binding specifiers and body, a locally defined
+foreign structure type foo> can be referenced by its name using
+(struct foo)>.
+
+
+
+
+External Foreign Variables>
+
+
+External foreign names are strings, and Lisp names are symbols. When
+an external foreign value is represented using a Lisp variable, there
+must be a way to convert from one name syntax into the other. The
+macros extern-alien>, define-alien-variable> and
+define-alien-routine> use this conversion heuristic:
+
+ Alien names are converted to Lisp names by uppercasing and
+ replacing underscores with hyphens.
+ Conversely, Lisp names are converted to alien names by
+ lowercasing and replacing hyphens with underscores.
+ Both the Lisp symbol and alien string names may be
+ separately specified by using a list of the form
+ (alien-string lisp-symbol)>
+
+
+(sb-alien:define-alien-variable name type)>
+
+
+The define-alien-variable> macro
+defines name> as an external foreign variable of the
+specified foreign type>. name> and type> are not
+evaluated. The Lisp name of the variable (see above) becomes a
+global alien variable. Global alien variables
+are effectively ``global symbol macros''; a reference to the
+variable fetches the contents of the external variable. Similarly,
+setting the variable stores new contents---the new contents must be
+of the declared type>. Someday, they may well be implemented
+using the &ANSI; define-symbol-macro> mechanism, but
+as of &SBCL; 0.7.5, they are still implemented using an older
+more-or-less parallel mechanism inherited from &CMUCL;.
+
+
+
+For example, to access a C-level counter foo>, one could
+write
+
+(define-alien-variable "foo" int)
+;; Now it is possible to get the value of the C variable foo simply by
+;; referencing that Lisp variable:
+(print foo)
+(setf foo 14)
+(incf foo)
+
+
+(sb-alien:get-errno)>
+
+
+Since in modern C libraries, the errno> "variable" is typically
+no longer a variable, but some bizarre artificial construct
+which behaves superficially like a variable within a given thread,
+it can no longer reliably be accessed through the ordinary
+define-alien-variable> mechanism. Instead, &SBCL; provides
+the operator sb-alien:get-errno> to allow Lisp code to read it.
+
+
+(sb-alien:extern-alien name type)>
+
+
+The extern-alien> macro
+returns an alien with the specified type> which
+points to an externally defined value. name> is not evaluated,
+and may be either a string or a symbol. type> is
+an unevaluated alien type specifier.
+
+
+
+
+Foreign Data Structure Examples>
+
+
+
+Now that we have alien types, operations and variables, we can manipulate
+foreign data structures. This C declaration
+
+struct foo {
+ int a;
+ struct foo *b[100];
+};
+can be translated into the following alien type:
+(define-alien-type nil
+ (struct foo
+ (a int)
+ (b (array (* (struct foo)) 100))))
+
+
+
+Once the foo> alien type has been defined as above,
+the C expression
+
+struct foo f;
+f.b[7].a
+can be translated in this way:
+
+(with-alien ((f (struct foo)))
+ (slot (deref (slot f 'b) 7) 'a)
+ ;;
+ ;; Do something with f...
+ )
+
+
+
+Or consider this example of an external C variable and some accesses:
+
+struct c_struct {
+ short x, y;
+ char a, b;
+ int z;
+ c_struct *n;
+};
+extern struct c_struct *my_struct;
+my_struct->x++;
+my_struct->a = 5;
+my_struct = my_struct->n;
+which can be manipulated in Lisp like this:
+
+(define-alien-type nil
+ (struct c-struct
+ (x short)
+ (y short)
+ (a char)
+ (b char)
+ (z int)
+ (n (* c-struct))))
+(define-alien-variable "my_struct" (* c-struct))
+(incf (slot my-struct 'x))
+(setf (slot my-struct 'a) 5)
+(setq my-struct (slot my-struct 'n))
+
+
+
+
+Loading Unix Object Files>
+
+
+Foreign object files can be loaded into the running Lisp process by
+calling the functions load-foreign> or
+load-1-foreign>.
+
+
+ The sb-alien:load-1-foreign> function is the more
+primitive of the two operations. It loads a single object file. into
+the currently running Lisp. The external symbols defining routines and
+variables are made available for future external references (e.g. by
+extern-alien>). Forward references to foreign symbols
+aren't supported: load-1-foreign> must be run before any
+of the defined symbols are referenced.
+
+
+sb-alien:load-foreign> is built in terms of
+load-1-foreign> and some other machinery
+like sb-ext:run-program>.
+It accepts a list of files and libraries,
+and runs the linker on the files and
+libraries, creating an absolute Unix object file which is then
+processed by load-1-foreign>.
+
+As of &SBCL; 0.7.5, all foreign code (code loaded
+with load-1-function> or load-function>) is
+lost when a Lisp core is saved with
+sb-ext:save-lisp-and-die>, and no attempt is made to
+restore it when the core is loaded. Historically this has been an
+annoyance both for &SBCL; users and for &CMUCL; users.
+It's hard to solve this problem completely cleanly, but some
+generally-reliable partial solution might be useful. Once someone in
+either camp gets sufficiently annoyed to create it, &SBCL; is
+likely to adopt some mechanism for automatically restoring foreign
+code when a saved core is loaded.
+
+
+
+Foreign Function Calls>
+
+
+The foreign function call interface allows a Lisp program to call
+many functions written in languages that use the C calling convention.
+
+
+
+Lisp sets up various signal handling routines and other environment
+information when it first starts up, and expects these to be in place
+at all times. The C functions called by Lisp should not change the
+environment, especially the signal handlers: the signal handlers
+installed by Lisp typically have interesting flags set (e.g to request
+machine context information, or for signal delivery on an alternate
+stack) which the Lisp runtime relies on for correct operation.
+Precise details of how this works may change without notice between
+versions; the source, or the brain of a friendly &SBCL; developer,
+is the only documentation. Users of a Lisp built with the :sb-thread
+feature should also read the Threading section
+
+of this manual
+
+The alien-funcall> Primitive
+
+(sb-alien:alien-funcall alien-function &rest arguments)>
+
+
+The alien-funcall> function is the foreign function call
+primitive: alien-function> is called with the supplied
+arguments> and its C return value is returned as a Lisp value.
+The alien-function> is an arbitrary
+run-time expression; to refer to a constant function, use
+extern-alien> or a value defined by
+define-alien-routine>.
+
+
+
+The type of alien-function>
+must be (alien (function ...))>
+or (alien (* (function ...)))>.
+The function type is used to
+determine how to call the function (as though it was declared with
+a prototype.) The type need not be known at compile time, but only
+known-type calls are efficiently compiled. Limitations:
+
+ Structure type return values are not implemented.>>
+ Passing of structures by value is not implemented.>>
+
+
+
+Here is an example which allocates a (struct foo)>, calls a foreign
+function to initialize it, then returns a Lisp vector of all the
+(* (struct foo))> objects filled in by the foreign call:
+
+;; Allocate a foo on the stack.
+(with-alien ((f (struct foo)))
+ ;; Call some C function to fill in foo fields.
+ (alien-funcall (extern-alien "mangle_foo" (function void (* foo)))
+ (addr f))
+ ;; Find how many foos to use by getting the A field.
+ (let* ((num (slot f 'a))
+ (result (make-array num)))
+ ;; Get a pointer to the array so that we don't have to keep extracting it:
+ (with-alien ((a (* (array (* (struct foo)) 100)) (addr (slot f 'b))))
+ ;; Loop over the first N elements and stash them in the result vector.
+ (dotimes (i num)
+ (setf (svref result i) (deref (deref a) i)))
+ ;; Voila.
+ result)))
+
+
+
+
+The define-alien-routine> Macro>
+
+(sb-alien:define-alien-routine} name result-type &rest arg-specifiers)>
+
+
+The define-alien-routine> macro is a convenience
+for automatically generating Lisp
+interfaces to simple foreign functions. The primary feature is the
+parameter style specification, which translates the C
+pass-by-reference idiom into additional return values.
+
+
+
+name> is usually a string external symbol, but may also be a
+symbol Lisp name or a list of the foreign name and the Lisp name.
+If only one name is specified, the other is automatically derived
+as for extern-alien>.
+result-type> is the alien type of the return value.
+
+
+
+Each element of the arg-specifiers> list
+specifies an argument to the foreign function, and is
+of the form
+(aname atype &optional style)
+aname> is the symbol name of the argument to the constructed
+function (for documentation). atype> is the alien type of
+corresponding foreign argument. The semantics of the actual call
+are the same as for alien-funcall>. style>
+specifies how this argument should be handled at call and return time,
+and should be one of the following
- Type Translations>>
- System Area Pointers>>
- Alien Objects>>
- Alien Types>>
- Alien Operations>>
- Alien Variables>>
- Alien Function Calls>>
+ :in>specifies that the argument is
+ passed by value. This is the default. :in> arguments
+ have no corresponding return value from the Lisp function.
+
+ :copy> is similar to :in>,
+ but the argument is copied
+ to a pre-allocated object and a pointer to this object is passed
+ to the foreign routine.
+ :out> specifies a pass-by-reference
+ output value. The type of the argument must be a pointer to
+ a fixed-sized object (such as an integer or pointer).
+ :out> and :in-out> style cannot
+ be used with pointers to arrays, records or functions. An
+ object of the correct size is allocated on the stack, and
+ its address is passed to the foreign function. When the
+ function returns, the contents
+ of this location are returned as one of the values of the Lisp
+ function (and the location is automatically deallocated).
+
+ :in-out> is a combination of
+ :copy> and :out>.
+ The argument is copied to a pre-allocated object and a pointer to
+ this object is passed to the foreign routine. On return, the
+ contents of this location is returned as an additional value.
+
-
\ No newline at end of file
+
+
+Any efficiency-critical foreign interface function should be inline
+expanded, which can be done by preceding the
+define-alien-routine> call with:
+(declaim (inline lisp-name))
+In addition to avoiding the Lisp call overhead, this allows
+pointers, word-integers and floats to be passed using non-descriptor
+representations, avoiding consing.)
+
+
+
+
+
+define-alien-routine> Example
+
+
+Consider the C function cfoo>
+with the following calling convention:
+
+void
+cfoo (str, a, i)
+ char *str;
+ char *a; /* update */
+ int *i; /* out */
+{
+ /* body of cfoo(...) */
+}
+This can be described by the following call to
+define-alien-routine>:
+
+(define-alien-routine "cfoo" void
+ (str c-string)
+ (a char :in-out)
+ (i int :out))
+The Lisp function cfoo> will have
+two arguments (str> and a>)
+and two return values (a> and i>).
+
+
+
+Calling Lisp From C>
+
+
+Calling Lisp functions from C is sometimes possible, but is extremely
+hackish and poorly supported as of &SBCL; 0.7.5.
+See funcall0> ... funcall3> in
+the runtime system. The
+arguments must be valid &SBCL; object descriptors (so that
+e.g. fixnums must be
+left-shifted by 2.) As of &SBCL; 0.7.5, the format
+of object descriptors is documented only by the source code and, in parts,
+by the old &CMUCL; "INTERNALS" documentation.
+
+ Note that the garbage collector moves objects, and won't be
+able to fix up any references in C variables. There are three
+mechanisms for coping with this:
+
+
+The sb-ext:purify> moves all live Lisp
+data into static or read-only areas such that it will never be moved
+(or freed) again in the life of the Lisp session
+
+sb-sys:with-pinned-objects is a
+macro which arranges for some set of objects to be pinned in memory
+for the dynamic extent of its body forms. On ports which use the
+generational garbage collector (as of &SBCL; 0.8.3, only the x86) this
+has a page granularity - i.e. the entire 4k page or pages containing
+the objects will be locked down. On other ports it is implemented by
+turning off GC for the duration (so could be said to have a
+whole-world granularity).
+
+Disable GC, using the without-gcing
+macro or gc-off call.
+
+
+
+
+
+
+Step-By-Step Example of the Foreign Function Interface>
+
+
+This section presents a complete example of an interface to a somewhat
+complicated C function.
+
+
+
+Suppose you have the following C function which you want to be able to
+call from Lisp in the file test.c>
+
+struct c_struct
+{
+ int x;
+ char *s;
+};
+
+struct c_struct *c_function (i, s, r, a)
+ int i;
+ char *s;
+ struct c_struct *r;
+ int a[10];
+{
+ int j;
+ struct c_struct *r2;
+
+ printf("i = %d\n", i);
+ printf("s = %s\n", s);
+ printf("r->x = %d\n", r->x);
+ printf("r->s = %s\n", r->s);
+ for (j = 0; j < 10; j++) printf("a[%d] = %d.\n", j, a[j]);
+ r2 = (struct c_struct *) malloc (sizeof(struct c_struct));
+ r2->x = i + 5;
+ r2->s = "a C string";
+ return(r2);
+};
+
+
+
+It is possible to call this C function from Lisp using the file
+test.lisp> containing
+
+(cl:defpackage "TEST-C-CALL" (:use "CL" "SB-ALIEN" "SB-C-CALL"))
+(cl:in-package "TEST-C-CALL")
+
+;;; Define the record C-STRUCT in Lisp.
+(define-alien-type nil
+ (struct c-struct
+ (x int)
+ (s c-string)))
+
+;;; Define the Lisp function interface to the C routine. It returns a
+;;; pointer to a record of type C-STRUCT. It accepts four parameters:
+;;; I, an int; S, a pointer to a string; R, a pointer to a C-STRUCT
+;;; record; and A, a pointer to the array of 10 ints.
+;;;
+;;; The INLINE declaration eliminates some efficiency notes about heap
+;;; allocation of alien values.
+(declaim (inline c-function))
+(define-alien-routine c-function
+ (* (struct c-struct))
+ (i int)
+ (s c-string)
+ (r (* (struct c-struct)))
+ (a (array int 10)))
+
+;;; a function which sets up the parameters to the C function and
+;;; actually calls it
+(defun call-cfun ()
+ (with-alien ((ar (array int 10))
+ (c-struct (struct c-struct)))
+ (dotimes (i 10) ; Fill array.
+ (setf (deref ar i) i))
+ (setf (slot c-struct 'x) 20)
+ (setf (slot c-struct 's) "a Lisp string")
+
+ (with-alien ((res (* (struct c-struct))
+ (c-function 5 "another Lisp string" (addr c-struct) ar)))
+ (format t "~&back from C function~%")
+ (multiple-value-prog1
+ (values (slot res 'x)
+ (slot res 's))
+
+ ;; Deallocate result. (after we are done referring to it:
+ ;; "Pillage, *then* burn.")
+ (free-alien res)))))
+
+
+
+To execute the above example, it is necessary to compile the C routine,
+e.g.:
+cc -c test.c>
+(In order to enable incremental loading with some linkers, you may need
+to say
+cc -G 0 -c test.c>)
+
+
+
+Once the C code has been compiled, you can start up Lisp and load it in:
+sbcl>.
+Lisp should start up with its normal prompt.
+
+
+Within Lisp,
+compile the Lisp file. (This step can be done separately. You don't
+have to recompile every time.)
+(compile-file "test.lisp")>
+
+
+Within Lisp, load the foreign object file to define the necessary
+symbols:
+(load-foreign "test.o")>.
+This must be done before loading any code that refers
+to these symbols.
+
+
+
+Now you can load the compiled Lisp ("fasl") file into Lisp:
+(load "test.fasl")>
+And once the Lisp file is loaded, you can call the
+Lisp routine that sets up the parameters and calls the C
+function:
+(test-c-call::call-cfun)>
+
+
+
+The C routine should print the following information to standard output:
+
+i = 5
+s = another Lisp string
+r->x = 20
+r->s = a Lisp string
+a[0] = 0.
+a[1] = 1.
+a[2] = 2.
+a[3] = 3.
+a[4] = 4.
+a[5] = 5.
+a[6] = 6.
+a[7] = 7.
+a[8] = 8.
+a[9] = 9.
+After return from the C function,
+the Lisp wrapper function should print the following output:
+back from C function
+And upon return from the Lisp wrapper function,
+before the next prompt is printed, the
+Lisp read-eval-print loop should print the following return values:
+
+
+10
+"a C string"
+
+
+
+
+
+