All Manuals > LispWorks Foreign Language Interface User Guide and Reference Manual > 7 Function, Macro and Variable Reference

NextPrevUpTopContentsIndex

define-foreign-converter

Macro
Summary

Defines a new FLI type specifier that converts to or from another type specifier.

Package

fli

Signature

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

Arguments

type-name

A symbol naming the new FLI type.

lambda-list

A lambda list which is the argument list of the new FLI type.

object-names

A symbol or a list of two symbols

foreign-type

A macro expansion form that evaluates to a FLI type descriptor

foreign-to-lisp

A macro expansion form to convert between Lisp and the FLI.

lisp-to-foreign

A macro expansion form to convert between the FLI and Lisp.

predicate

A macro expansion form to check whether a Lisp object is of this type.

tested-value

A macro expansion form to give an error if a Lisp object is not of this type.

error-form

A macro expansion form to give an error if predicate returns false.

documentation

A string.

object-names ::= object-name | ( lisp-object-name foreign-object-name )

Values

type-name

The name of the new FLI converter type

Description

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.

Examples

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
See also

define-foreign-type
define-opaque-pointer
:wrapper
Parameterized types


LispWorks Foreign Language Interface User Guide and Reference Manual - 29 Sep 2017

NextPrevUpTopContentsIndex