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.
(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.)
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)
(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.
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) => 10If 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.