| Allegro CL version 9.0 Unrevised from 8.2 to 9.0. 8.2 version |
Arguments: lispname &key entry-point unconverted-entry-name arguments pass-types arg-checking prototype return-type language convert-symbol print address remember-address call-direct callback strings-convert
This operator is obsolete and maintained for backwards compatibility only. It has been replaced by the macro def-foreign-call. All new code should use that macro.
This macro defines the calling convention which allows Lisp to call a foreign function correctly, passing arguments of the correct type, and interpreting the returned value correctly. lisp-name is the name (a symbol) by which lisp will refer to the foreign function.
If the entry point (either the value of entry-point or determined by other arguments as described below) does not exist, no error will be signaled when defforeign is called. Instead, the error will be signaled when the function defined by defforeign is called. This makes foreign functions more like Lisp functions -- if you define foo to call the undefined function bar, the error is signaled when foo is called, not when foo is defined.
The function defforeign creates a function identified by lisp-name, which passes its arguments through to the foreign code and returns the return-value of the foreign function to Lisp. The default passing convention (which can be overridden by using the pass-types keyword argument to defforeign) depends on the type of arguments and the language. For example, C normally expects its arguments to be passed by value, Fortran expects arguments to be passed by address.
defforeign returns t
if it successfully defines the
foreign function. It returns nil
if it fails.
You can test whether or not an entry point exists with the function get-extern-code-address.
The following are the keyword arguments to defforeign.
Argument | Value | Description |
entry-point | foreign-name | This keyword's value foreign-name
is the name of the entry point as found in the loaded foreign
namespace. If no value is specified, the default depends on other
arguments. The determination of the entry-point need not happen
until the defforeign form is loaded
into (or evaluated within) Lisp and not when a file containing a
defforeign
form is compiled into a fasl
file. If determination of the entry-point is delayed until a
fasl file is loaded, the
same fasl file can be used
on different platforms despite different conventions for naming
entry points (some platforms prepend a _, some append, and some do
not add _'s).
The entry-point name is determined as follows: If entry-point is specified, it is used at compile time. If entry-point is not specified but convert-symbol is, (convert-symbol lisp-name) where convert-symbol is the conversion function given in the keyword argument convert-symbol described below, is used as the entry point at compile time. If neither entry-point nor convert-symbol are specified, unconverted-entry-name is stored at compile time and converted (with convert-to-lang) only when the resulting fasl file is loaded. This allows the same fasl files to be used on various platforms. unconverted-entry-name defaults to the symbol name of lisp-name. Late conversion is the recommended behavior, so neither this argument nor convert-symbol should be specified. This argument and unconverted-entry-name should not both be specified. |
unconverted-entry-name | unconverted-entry-name | unconverted-entry-name should evaluate to a string. The method for determining the entry point name is given in the description of entry-point just above. If a value for this argument is specified, it is stored until the defforeign form defining the foreign function is loaded (or evaluated). At that time, unconverted-entry-name is converted with convert-to-lang to produce the entry-point name. |
arguments | (argument-type+) | This specifies the types of arguments that will be
passed to the foreign function. Its value must be a list of valid
lisp types (e.g. the expressions integer, string, (simple-array
double-float), etc.), or t, which converts arguments according to
their type, whatever they are, or nil ,
which means no arguments. When unspecified, this argument defaults
to t.
The special type |
pass-types | pass-convention+ | This keyword specifies the passing convention of
each argument. The choices are :by-address, meaning pass by
address (Fortran style) and :by-value, meaning pass by value (C
style). The default is the style of the language specified, so
users will rarely have to use this keyword. If the C code passes
arguments by address, however, then this keyword should be used
and its value should be a list of the same length as the argument
list with elements :by-value if the corresponding argument is
passed by value and :by-address if it is passed by address.
In addition to :by-value and :by-address, one can specify :normal and :non-array-by-address. :normal means to use the normal pass-type based on the value of the :language argument. :non-array-by-address means to pass the argument by address if the corresponding argument specified in the arguments list is not an array. |
arg-checking | t-or-nil | This argument defaults to t, in which case Lisp
will check that the arguments passed through to the foreign
function are of the types specified in
arguments. This argument is ignored if
arguments is t. This argument must be nil if call-direct is
specified t (otherwise the call will not
be inlined). |
prototype | proto | This keyword is now effective on most
platforms. This keyword supports argument passing for machines
with ANSI C compilers which use function argument prototyping. C
functions written with ANSI C prototyping expect arguments to be
passed in a specific format. Before the advent of ANSI C
prototyping, one did not know what format the callee function
expected, so functions always passed in the largest value.
The
default is For example: (ff:defforeign 'blarg :arguments (integer single-float single-float) :prototype (t t)) would say that the first two args are prototyped and the third is not. To use defforeign on a function defined with a prototype, one must list the argument type with the argument keyword and have the prototype keyword argument true. If one has argument checking enabled with the arg-checking keyword argument, then foreign function calling will be strict about getting the correct floating point type. |
return-type | return-type | The value of return-type must be one of the keywords
:void indicates no value is returned; :lisp indicates a Lisp value is returned
(normally used only if a C program returns a value accessed by the C routine
lisp_value()). The other keywords indicate values of the type named by the keyword. If the
value is :boolean, the function will return When unspecified, this argument defaults to :integer. |
language | language-name | The language-name must be either of the keywords :c, for C, or :fortran, for Fortran. When unspecified, this argument defaults to :c. This argument is ignored if entry-point is specified. |
t-or-nil | If t, information useful for debugging will be printed to *terminal-io*.
This argument defaults to nil . |
|
convert-symbol | con-function | Note: specifying a value for this argument is not
recommended. See the description of
entry-point above for information on how Lisp
determines the entry-point name for a foreign function. If a value
for this argument is specified (and no value is specified for
entry-point or
unconverted-entry-name), the entry-point name
will be determined at compile time by applying the function which
is the value of this argument to lisp-name. The benefits of
determining the entry point only when the fasl file containing the
defforeign
form is loaded (which allows for portability) is lost.
This keyword's value con-function is the name of the function that does the conversion of the Lisp name to an entry-point name. The function must take as arguments a symbol and the keyword :language, and must return a string recognizable to the operating system as an entry-point name. |
call-direct | t-or-nil | The default value of this argument
is nil . If this value
is t , then the compiler will attempt to
inline calls to the foreign function being defined by this call
to defforeign. If the value of
:call-direct is t then the :arguments
keyword argument must be a list of arguments rather
than t
and arg-checking must be
nil (otherwise :call-direct's value will
be ignored). :callback may be t or
nil but if it is t, extra code must be
included to allow for the callback so the inlined call is
slower.
A :call-direct foreign function will return the type specified by :return-type. In earlier releases, a double-float was sometimes returned when :return-type was :single-float. because the C routine returned a double and Lisp did not convert it. Starting in 4.3, Lisp converts the value returned by C if necessary. |
callback | callback | Because Allegro CL uses (on some platforms) the
:os-threads model of multiprocessing, it is not
possible to guarantee that Lisp code will not run while a foreign
function defined to Lisp with defforeign is running
(essentially what :callback nil did in earlier relases on
Unix). Therefore, whatever is specified for this argument, t is the value used. See the
release-heap keyword argument of
def-foreign-call. |
method-index | nil (the default) or an index into C++ table, as described at
right. |
This argument allows for calling of C++ style member-methods. The value, if specified, must be an integer index into the virtual table of the C++ class. Symbolic index specifications are not directly supported. |
strings-convert | nil
or t . Default
is t . |
This argument is only supported on 16-bit
character Lisps. (Allegro CL can run with 8-bit characters or
16-bit characters. See this section
of startup.htm for the various Allegro CL
images.) This argument assists in having the foreign-function
interface handle Allegro CL's 16-bit strings automatically. When
the strings-convert is true, then when any of
the specified arguments at defforeign time are declared
directly or indirectly as (*
:char) , defforeign augments the
function wrapping the low-level foreign function call so that for
each (* :char) declared argument, a check is
made at runtime to see if that declaration's corresponding value
is a string. If it is, then that value is converted at runtime to
native-string format using a dynamic-extent array, and this new
array is passed in place of the original string argument to
low-level foreign function call. See Foreign-Functions
in iacl.htm for full details and examples (the
examples use def-foreign-call). |
See ftype.htm for information on foreign types in Allegro CL and foreign-functions.htm for general information on foreign functions in Allegro CL.
Copyright (c) 1998-2019, Franz Inc. Oakland, CA., USA. All rights reserved.
This page was not revised from the 8.2 page.
Created 2012.5.30.
| Allegro CL version 9.0 Unrevised from 8.2 to 9.0. 8.2 version |