SBCL User Manual
Prev | Chapter 5. The Foreign Function Interface | Next

# 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

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

Prev | Home | Next
The Foreign Function Interface | Up | Operations On Foreign Values