Next: , Previous: defbitfield, Up: Foreign Types



— Macro: defcstruct name-and-options &body doc-and-slots ⇒ name

name-and-options ::= structure-name | (structure-name &key size)

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

Arguments and Values

The name of new structure type.
A documentation string, ignored.
A symbol naming the slot. It must be unique among slot names in this structure.
Use this option to override the size (in bytes) of the struct.
The type specifier for the slot.
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.
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