Previous: Foreign Types and Lisp Types, Up: Foreign Types

#### 8.2.3 Foreign Type Specifiers

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`&rest dimensions)` describes array of the specified `dimensions`, holding elements of type foo. Note that (unlike in C) `(*` foo`)` and `(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, as guessed by the SBCL internals. An optional `:alignment` keyword argument can be specified for each field to explicitly control the alignment of a field. 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 symbols. If name is `nil`, then the type is anonymous. Each element of the specs list is either a Lisp symbol, or a list `(`symbol 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 &key external-format element-type)` 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`.

  External format conversion is automatically done when Lisp strings are passed to foreign code, or when foreign strings are passed to Lisp code. If the type specifier has an explicit `external-format`, that external format will be used. Otherwise a default external format that has been determined at SBCL startup time based on the current locale settings will be used. For example, when the following alien routine is called, the Lisp string given as argument is converted to an `ebcdic` octet representation.

                (define-alien-routine test int (str (c-string :external-format :ebcdic-us)))

  Lisp strings of type `base-string` 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, assuming that the `external-format` and `element-type` of the `c-string` type are compatible with the internal representation of the string. For an SBCL built with Unicode support that means an `external-format` of `:ascii` and an `element-type` of `base-char`. Without Unicode support the `external-format` can also be `:iso-8859-1`, and the `element-type` can also be `character`. If the `external-format` or `element-type` is not compatible, or the string is a `(simple-array character (*))`, this data is copied by the implementation as required.

  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`.