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)))
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.
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.
Note: 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 CMU CL 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.
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.