define-foreign-converter type-name lambda-list object-names &key foreign-type foreign-to-lisp lisp-to-foreign predicate tested-value error-form documentation => type-name
A symbol naming the new FLI type.
A lambda list which is the argument list of the new FLI type.
A symbol or a list of two symbols
A macroexpansion form that evaluates to a FLI type descriptor
A macroexpansion form to convert between Lisp and the FLI.
A macroexpansion form to convert between the FLI and Lisp.
A macroexpansion form to check if a Lisp object is of this type.
A macroexpansion form to give an error if a Lisp object is not of this type.
A macroeXpansion form to give an error if predicate returns false.
A string.
object-names ::= object-name | ( lisp-object-name foreign-object-name )
Note: this macro is for advanced use of the FLI type system. See define-foreign-type for simple aliasing of FLI type descriptors.
The macro
define-foreign-converter
defines a new FLI type specifier
type-name
that wraps another FLI type specifier and optionally performs data conversion and type checking. The string
documentation
is associated with
type-name
with the define-foreign-type documentation type.
The lambda list of the new FLI type specifier is lambda-list and its variables are available for use in the foreign-type , foreign-to-lisp , lisp-to-foreign , predicate and tested-value forms.
If object-names is a symbol object-name , then it provides the name of a variable for use in all of the macroexpansion forms. Otherwise object-names should be a list of the form ( lisp-object-name foreign-object-name ), where lisp-object-name provides the name of a variable for use in the lisp-to-foreign , predicate and tested-value forms and foreign-object-name provides the name of a variable for use in the foreign-to-lisp form.
When the new FLI type is used, the foreign-type form is evaluated to determine the underlying FLI type descriptor to be converted. It can use variables bound by lambda-list , but not object-names .
When type-name is used to convert a foreign value to Lisp (for example when as the result-type in define-foreign-function), the foreign-to-lisp form is evaluated to determine how the conversion should be made. It works like a macroexpansion function, so should return a form that converts the foreign value, which will be bound to object-name (or foreign-object-name ). It can use variables bound by lambda-list .
When type-name is used to convert a Lisp value to a foreign value (for example in the argument list of define-foreign-function), the type of the Lisp value can be checked before conversion using tested-value and predicate and then converted using lisp-to-foreign as detailed below.
If tested-value is specified, it is used as a macroexpansion function that returns a form that must return object-name (or lisp-object-name ) if it is of the required type or give an error. It can use variables bound by lambda-list , but not object-names .
Otherwise, if predicate is specified, it is used as a macroexpansion function that returns a form that must return true if object-name (or lisp-object-name ) is of the required type. If predicate is specified, then error-form can be specified as a macroexpansion function that signals an error about object-name (or lisp-object-name ) not being of the required type. If error-form is omitted, a default error is signaled. Both predicate and error-form can use variables bound by lambda-list , but not object-names .
If both tested-value and predicate are omitted, then no type checking is performed.
After type checking, lisp-to-foreign is used as a macroexpansion function that returns a form that converts the Lisp object object-name (or lisp-object-name ) to the underlying FLI type foreign-type . It can use variables bound by lambda-list , but not object-names .
This defines a FLI type
(real-double
lisp-type
)
, which allows any real value in Lisp to be passed to foreign code as a double precision float. When a foreign value is converted to Lisp, it is coerced to
type
:
(fli:define-foreign-converter real-double (lisp-type)
object
:foreign-type :double
:foreign-to-lisp `(coerce ,object ',lisp-type)
:lisp-to-foreign `(coerce ,object 'double-float)
:predicate `(realp ,object))
This defines a FLI type
int-signum
, which uses -1, 0 and 1 for values on the foreign side. There is no
foreign-to-lisp
form specified, so it will return these values to Lisp too:
(fli:define-foreign-converter int-signum () object
:foreign-type :int
:lisp-to-foreign `(signum ,object))
This defines a FLI type
(bigger-in-lisp
n
)
, which is an integer type for values that are
n
bigger in Lisp than on the foreign side.
(fli:define-foreign-converter bigger-in-lisp
(&optional (n 1))
object
:foreign-type :int
:foreign-to-lisp `(+ ,object ,n)
:lisp-to-foreign `(- ,object ,n)
:predicate `(integerp ,object))
(fli:with-dynamic-foreign-objects ((x :int 10))
(fli:dereference x :type '(bigger-in-lisp 2))) => 12