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 macro expansion form that evaluates to a FLI type descriptor
A macro expansion form to convert between Lisp and the FLI.
A macro expansion form to convert between the FLI and Lisp.
A macro expansion form to check whether a Lisp object is of this type.
A macro expansion form to give an error if a Lisp object is not of this type.
A macro expansion 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 macro expansion 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 macro expansion 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 macro expansion 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 macro expansion 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 macro expansion 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 macro expansion 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
LispWorks Foreign Language Interface User Guide and Reference Manual - 29 Sep 2017