Operations On Foreign Values
Prev | Chapter 5. The Foreign Function Interface | Next

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

Prev | Up | Next
Foreign Types | Home | Foreign Variables