Package: cffi

Macro defcstruct

Lambda List

defcstruct (name-and-options &body fields)


name-and-options ::= structure-name | (structure-name &key size)
doc-and-slots ::= [docstring] { (slot-name slot-type &key count offset) }*


structure-name -- The name of new structure type.
docstring -- A documentation string, ignored.
slot-name -- A symbol naming the slot. It must be unique among slot names in this structure.
size -- Use this option to override the size (in bytes) of the struct.
slot-type -- The type specifier for the slot.
count -- Used to declare an array of size count inside the structure. Defaults to 1 as such an array and a single element are semantically equivalent.
offset -- Overrides the slot's offset. The next slot's offset is calculated based on this one.


This defines a new CFFI aggregate type akin to C structs. In other words, it specifies that foreign objects of the type structure-name are groups of different pieces of data, or "slots", of the slot-types, distinguished from each other by the slot-names. Each structure is located in memory at a position, and the slots are allocated sequentially beginning at that point in memory (with some padding allowances as defined by the C ABI, unless otherwise requested by specifying an offset from the beginning of the structure (offset 0).

In other words, it is isomorphic to the C struct, giving several extra features.

There are two kinds of slots, for the two kinds of CFFI types:
Contain a single instance of a type that canonicalizes to a built-in type, such as :long or :pointer. Used for simple CFFI types.
Contain an embedded structure or union, or an array of objects. Used for aggregate CFFI types.
The use of CLOS terminology for the structure-related features is intentional; structure definitions are very much like classes with (far) fewer features.


  (defcstruct point
    "Point structure."
    (x :int)
    (y :int))

CFFI> (with-foreign-object (ptr 'point) ;; Initialize the slots (setf (foreign-slot-value ptr 'point 'x) 42 (foreign-slot-value ptr 'point 'y) 42) ;; Return a list with the coordinates (with-foreign-slots ((x y) ptr point) (list x y))) => (42 42)

;; Using the :size and :offset options to define a partial structure. ;; (this is useful when you are interested in only a few slots ;; of a big foreign structure)

(defcstruct (foo :size 32) "Some struct with 32 bytes." ; <16 bytes we don't care about> (x :int :offset 16) ; an int at offset 16 (y :int) ; another int at offset 16+sizeof(int) ; <a couple more bytes we don't care about> (z :char :offset 24)) ; a char at offset 24 ; <7 more bytes ignored (since size is 32)>

CFFI> (foreign-type-size 'foo) => 32

;;; Using :count to define arrays inside of a struct. (defcstruct video_tuner (name :char :count 32))

See also