define-foreign-callable ( foreign-name &key encode language result-type result-pointer no-check calling-convention ) ( {args }*) &body body => lisp-name
args
::= {
arg-name
} | (
arg-name
arg-type
)
A string or symbol naming the Lisp callable function created.
By default, LispWorks performs automatic name encoding to translate foreign-name
If you want to explicitly specify an encoding, the encode option can be one of the following:
:source
tells LispWorks that
foreign-name
is the function name to call from the foreign source code. This is the default value of
encoding
.
:object
tells LispWorks that
foreign-name
is the literal name to be called in the foreign object code.
:lisp
tells LispWorks that if
foreign-name
is a Lisp symbol, it must be translated and encoded.
:dbcs
adds a suffix onto the function name which will automatically change depending on whether Lisp image is started up in the Windows NT or Windows 95 operating system. The suffix is "
A
" for Windows 95 and "
W
" for Windows NT.
The language in which the foreign calling code is written. The default is
:c
.
The FLI type of the Lisp foreign callable function's return value which is passed back to the calling code.
A variable which will be bound to a foreign pointer into which the result should be written when the result-type is an aggregate type.
If
nil
, the result of the foreign callable function, produced by
body
, is checked to see if matches the
result-type
, and an error is raised if they do not match. Setting
no-check
to
t
overrides this check.
Specifies the calling convention used.
:stdcall
is the calling convention used to call Win32 API functions and matches the C declarator
"__stdcall"
. This is the default on Windows.
:cdecl
is the default calling convention for C/C++ programs and matches the C declarator
"__cdecl"
. This is the default on Unix/Linux. There is no calling convention issue on Macintosh.
The arguments of the Lisp foreign callable function. Each argument can consist either of an
arg-name
, in which case LispWorks assumes it is an
:int
, or an
arg-name
and an
arg-type
, which is an FLI type.
A list of forms which make up the Lisp foreign callable function.
The macro
define-foreign-callable
defines a Lisp function that can be called from a foreign language, for example from a C function. When the Lisp function is called, data passed to it is converted to the appropriate FLI representation, which is translated to an appropriate Lisp representation for the Lisp part of the function. Once the callable function exits, any return values are converted back into an FLI format to be passed back to the calling language.
When the result-type is a aggregate type, an additional variable is bound in the body to allow the value of the function to be returned (the value returned by the body is ignored). This argument is named after the
result-pointer
argument or is named
result-pointer
in the current package if unspecifed. While the body is executing, the variable will be bound to a foreign pointer that points to an object of the type
result-type
. The body must set the slots in this foreign object in order for the value to be returned to the caller.
To make a function pointer referencing a foreign callable
Foo
, use:
(make-pointer :symbol-name "Foo")
The following example demonstrates the use of foreign callable. A foreign callable function,
square
, is defined, which takes an integer as its argument, and returns the square of the integer.
(fli:define-foreign-callable
("square" :result-type :int)
((arg-1 :int)) (* arg-1 arg-1))
The foreign callable function,
square
, can now be called from a foreign language. We can mimic a foreign call by using the define-foreign-function macro to define an FLI function to call
square
.
(fli:define-foreign-function (call-two "square")
((in-arg :int)) :result-type :int)
The
call-two
function can now be used to call
square
. The next command is an example of this.
(call-two 9)
This last example shows how the address of a foreign callable can be passed via a pointer object. The foreign library in this example is libgsl:
(fli:define-foreign-callable ("gsl-error-handler")
((reason (:reference-return :ef-mb-string))
(file (:reference-return :ef-mb-string))
(lineno :integer)
(gsl-errno :integer))
(error
"Error number ~a inside GSL [file: ~a, lineno ~a]: ~a"
gsl-errno file lineno reason))
(fli:define-foreign-function gsl-set-error-handler
((func :pointer))
:result-type :pointer)
To set the error handler, you would do:
(gsl-set-error-handler
(fli:make-pointer :symbol-name "gsl-error-handler"))