Package: cffi

Macro defbitfield

Lambda List

defbitfield (name-and-options &body masks)

Syntax

masks ::= [docstring] { (symbol value) }*
name-and-options ::= name | (name &optional (base-type :int))

Arguments

name -- The name of the new bitfield type.
docstring -- A documentation string, ignored.
base-type -- A symbol denoting a foreign type.
symbol -- A Lisp symbol.
value -- An integer representing a bitmask.

Details

The defbitfield macro is used to define foreign types that map lists of symbols to integer values.

If value is omitted, it will be computed as follows: find the greatest value previously used, including those so computed, with only a single 1-bit in its binary representation (that is, powers of two), and left-shift it by one. This rule guarantees that a computed value cannot clash with previous values, but may clash with future explicitly specified values.

Symbol lists will be automatically converted to values and vice versa when being passed as arguments to or returned from foreign functions, respectively. The same applies to any other situations where an object of a bitfield type is expected.

Types defined with defbitfield canonicalize to base-type which is :int by default.

Examples

  (defbitfield open-flags
    (:rdonly #x0000)
    :wronly               ;#x0001
    :rdwr                 ;...
    :nonblock
    :append
    (:creat  #x0200))
    ;; etc...

CFFI> (foreign-bitfield-symbols 'open-flags #b1101) => (:RDONLY :WRONLY :NONBLOCK :APPEND)

CFFI> (foreign-bitfield-value 'open-flags '(:rdwr :creat)) => 514 ; #x0202

(defcfun ("open" unix-open) :int (path :string) (flags open-flags) (mode :uint16)) ; unportable

CFFI> (unix-open "/tmp/foo" '(:wronly :creat) #o644) => #<an fd>

;;; Consider also the following lispier wrapper around open() (defun lispier-open (path mode &rest flags) (unix-open path flags mode))
 

See also