Next: , Previous: , Up: Foreign Functions   [Contents][Index]


65.4 User-Defined Types

As usual in most libraries written in C, objects carry an abstract type. These abstract types can be aliases for the built-in ones, ‘struct’s or ‘union’s composed by more atomic types.

For the bare aliasing of types, there is a macro define-ffi-type, which can also be used to construct unions, as well as arrays.

Macro: define-ffi-type name type

Associate name with FFI type. When defining global structures or unions, name may be nil, in that case name is derived from the name of type.

(define-ffi-type mytype unsigned-long)
     ⇒ mytype

Once a type is defined that way, it can be used as if it was a native C-type.

(ffi-type-p 'mytype)
     ⇒ t
(ffi-size-of-type 'mytype)
     ⇒ 4

As mentioned above, we look at the construction of arrays now.

(define-ffi-type myarray (array unsigned-long 8))
     ⇒ myarray
(ffi-size-of-type 'myarray)
     ⇒ 32

Similarly, unions and structs can be defined. For structs, however, there exists a more dedicated definition function, define-ffi-struct. This function also defines setter and getter forms which can be used to selectively set or get the slots in a structure.

Getting the value of a slot in a structure defined that way can be done with a function structname->slotname. Setting values is achieved by using setf on structname->slotname.

Macro: define-ffi-struct name &rest slots

Define a new structure of NAME and SLOTS.

(define-ffi-struct foo (sl1 unsigned-int) (sl2 char) (sl3 int))
     ⇒ (lambda (obj) "
Common Lisp lambda list:
  (foo->sl3 OBJ)

" (block foo->sl3 (let* ((--obj--temp-- (gensym "--obj--"))
(--nv--temp-- (gensym "--nv--"))) (list (list --obj--temp--) (list
obj) (list --nv--temp--) (let* ((obj --obj--temp--) (nv --nv--temp--))
(list (quote ffi-store) obj (list (quote ffi-slot-offset) (quote
(quote foo)) (quote (quote sl3))) (list (quote ffi-slot-type) (quote
(quote foo)) (quote (quote sl3))) nv)) (list (quote foo->sl3)
--obj--temp--)))))
(fboundp #'foo->sl1)
     ⇒ t
(fboundp #'foo->sl2)
     ⇒ t
(fboundp #'foo->sl2)
     ⇒ t

65.4.1 Enumerations

A special case of user-defined data are so called enumerations. Basically they are used to simultaneously define a large block of aliases. These are enumerated (beginning from 0) and are replaced by the according integers during the preprocessor time.

For convenience the SXEmacs FFI interface provides a similar functionality.

Macro: ffi-enum name &optional docstring &rest specs

Define an enumeration name. Optional argument docstring is a documentation string.

specs can be an arbitrary number of symbols which will be enumerated in the respective order.

Additionally the cells of specs may look like

foo = bar

to adhere a symbol ‘foo’ to the enumeration with the value of the symbol ‘bar’ (i.e. ‘foo’ is an alias of ‘bar’).

Moreover, it is possible to set the counter explicitly:

baz = 5

would assign a value of 5 to the symbol ‘baz’ and (by side-effect) set the counter to 6 for the next symbol.

The defined enumeration will result in a (defconst’d) variable name, the value is an alist of the form

((symbol . value) ...)’,

where ‘value’ is the C-value of ‘symbol’.

Furthermore, two functions (named name and name-value) will be defined. The first one is a simple lookup function returning the C-value of a passed symbol. The second does basically the same but returns the representing (elisp) integer of a symbol. Both functions return nil if the symbol is not in the enumeration.


Next: , Previous: , Up: Foreign Functions   [Contents][Index]