| Allegro CL version 8.2 Unrevised from 8.1 to 8.2. 8.1 version |
Arguments: name arglist &rest body
This macro creates a function that can be called from non-lisp code. It is intended that such a function be callable from lisp as well, but such functionality has not yet been provided. (This macro replaces the obsolete defun-c-callable.)
name must be a symbol representing the name of the new function to install.
arglist is an argument list
specification. Each argument is either a symbol representing the name
of an argument of type :long
, or it is a list of two
elements containing the argument name and foreign-type,
respectively.
The first form in the body can be a declaration
form, whose valid options are :convention
,
:unwind
, and :returning
;
somthing like:
(defun-foreign-callable my-callback () (declare (:convention :c)) ...)
The possible values of the options are:
:convention
: the convention provides for the
specialization of calling conventions due to language or
operating-system distinctions. The default convention is
:c
, and is adequate for most
situations. :fastcall
is also accepted. Other
values are distinguished by MS Windows-based systems including
:stdcall
, :method
, and
:fastcall
, but :fastcall
is not
supported and should not be specified. See Note 2: Possible
Values for Convention on the page for def-foreign-call.
:unwind
: on MS Windows based systems, defaults to
0, and to nil
on all other systems. May be
nil
or an integer.
:returning
: this specifies the type of what is
returned by the called function. It is ignored except when the
declared value includes a foreign struct type (either a
:struct
, a :union
, or a
:class
); when this occurs a hidden argument is
provided and the structure is arranged to be copied back to the
caller, according to the calling convention of the architecture. The
general form is
(ff:defun-foreign-callable foo (...) (declare (:returning <type>)) ...)
where <type>
is a foreign type or its name
specifying a structure. This declaration is intended to eventually
replace the convert-to-c-types argument in
register-foreign-callable, and
cannot be used with it.
New C++ and other language based systems tend to establish exception handlers, and set up their own equivalent of unwind-protects in their own langage. Lisp knows nothing about such exception handlers, and thus tends to trash the handler chains that have been built up whenever lisp code throws over non-lisp code to a catch form in lisp code deeper in the stack. The non-lisp code had been expecting either its own exception handling system to remove the exception from the chain on the stack, or else normal functional returns to unwind the stack in a normal fashion.
When the :unwind
value is nil
, then no special unwinding takes place. When the
argument is non-nil
(e.g. 0), then a special
"throw-by-returning-to-c" style of unwinding occurs; a throw occurs,
not by removing the stack (including the foreign code which might have
established handlers), but instead by returning the unwind-value to
that code, which should then remove its own handler and return. When
the foreign code returns, the lisp throw is again resumed until it is
completed, or until the next lisp-to-nonlisp transition is
encountered.
In order to use a function defined by defun-foreign-callable, the function must first be registered using register-foreign-callable.
What the foreign-callable function returns as a foreign value is
controlled by the call to register-foreign-callable (which
actually enables the foreign callable function). If the third
(optional) argument to register-foreign-callable is
nil
, an unconverted Lisp value is returned in
the foreign return register. Programmers must use the specifications
in [Allegro
directory]/misc/lisp.h to interpret this value. If the
third argument is t
, then the Lisp value of
the function is converted to a foreign value according to the default
conversion rules, and the resulting value is returned as the foreign
value returned by the Lisp function.
The body of the foreign callable Lisp function must be carefully coded to return a Lisp value that will trigger an appropriate conversion so that the desired foreign value will actually appear at the interface.
Consider this call to defun-foreign-callable:
(defun-foreign-callable gdbm-error-handler ((string (* :char))) (error "gdbm error: ~a." (native-to-string string)))
The call native-to-string is necessary because the string argument in the callback to Lisp is done with no string conversion at callback time. The value of the string argument as passed will be an integer representing a C address. native-to-string does the necessary conversion.
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-2016, Franz Inc. Oakland, CA., USA. All rights reserved.
This page was not revised from the 8.1 page.
Created 2010.1.21.
| Allegro CL version 8.2 Unrevised from 8.1 to 8.2. 8.1 version |