defforeign

Macro

Package: ff

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

This function 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 function 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.

ArgumentValueDescription
entry-point foreign-nameThis 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 :lisp is also accepted as an argument-type. Arguments specified :lisp are passed to foreign code unconverted. The format of Lisp objects is given in the sys:;misc;lisp.h file. Please be aware that if a Lisp object is modified inappropriately by foreign code, Lisp will likely fail unrecoverably. Also note that the Lisp object may be moved by the garbage collector so the reference may not be valid if it is stored by C for later processing.

pass-typespass-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-checkingt-or-nilThis 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).
prototypeprotoThis 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 nil. If proto is t, then all arguments will be prototyped. If the arguments are only partially prototyped (e.g. only the first few are prototyped), then the value of the prototype argument should be a list containing t's in the prototyped positions.

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-typereturn-typeThe value of return-type must be one of the keywords

:integer :fixnum :single-float :double-float :character :lisp :boolean :void

: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 t or nil as the foreign code returned a non-zero or 0 value.

When unspecified, this argument defaults to :integer.

languagelanguage-nameThe 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.
printt-or-nilIf t, information useful for debugging will be printed to *terminal-io*. This argument defaults to nil.
convert-symbolcon-functionNote: 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-directt-or-nilThe 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.

callbackcallbackBecause 5.0/5.0.1 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-indexnil (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.

See ftype.htm for information on foreign types in Allegro CL and foreign-functions.htm for general information on foreign functions in Allegro CL.

The documentation is described in introduction.htm and the index is in index.htm.

Copyright (c) 1998-2000, Franz Inc. Berkeley, CA., USA. All rights reserved.

Created 2000.10.5.