From 33b3b3c005d631ad169c99d851117b6155283730 Mon Sep 17 00:00:00 2001
From: toy <toy>
Date: Wed, 14 May 2003 17:32:44 +0000
Subject: [PATCH] Replace the section "Calling Lisp from C" with rudimentary
 info about callback support.

---
 docs/cmu-user/aliens.tex | 120 ++++++++++++++++++++++++++++++++++-----
 1 file changed, 106 insertions(+), 14 deletions(-)

diff --git a/docs/cmu-user/aliens.tex b/docs/cmu-user/aliens.tex
index 7efdb7408..2bdc7900c 100644
--- a/docs/cmu-user/aliens.tex
+++ b/docs/cmu-user/aliens.tex
@@ -727,20 +727,112 @@ and two return values (\var{a} and \var{i}).
 
 \subsection{Calling Lisp from C}
 
-Calling Lisp functions from C is sometimes possible, but is rather hackish.
-See \code{funcall0} ... \code{funcall3} in the \file{lisp/arch.h}.  The
-arguments must be valid \cmucl{} object descriptors (e.g.  fixnums must be
-left-shifted by 2.)  See \file{compiler/generic/objdef.lisp} or the derived
-file \file{lisp/internals.h} for details of the object representation.
-\file{lisp/internals.h} is mechanically generated, and is not part of the
-source distribution.  It is distributed in the \file{docs/} directory of the
-binary distribution.
-
-Note that the garbage collector moves objects, and won't be able to fix up any
-references in C variables, so either turn GC off or don't keep Lisp pointers
-in C data unless they are to statically allocated objects.  You can use
-\funref{purify} to place live data structures in static space so that they
-won't move during GC.
+% Calling Lisp functions from C is sometimes possible, but is rather hackish.
+% See \code{funcall0} ... \code{funcall3} in the \file{lisp/arch.h}.  The
+% arguments must be valid \cmucl{} object descriptors (e.g.  fixnums must be
+% left-shifted by 2.)  See \file{compiler/generic/objdef.lisp} or the derived
+% file \file{lisp/internals.h} for details of the object representation.
+% \file{lisp/internals.h} is mechanically generated, and is not part of the
+% source distribution.  It is distributed in the \file{docs/} directory of the
+% binary distribution.
+
+% Note that the garbage collector moves objects, and won't be able to fix up any
+% references in C variables, so either turn GC off or don't keep Lisp pointers
+% in C data unless they are to statically allocated objects.  You can use
+% \funref{purify} to place live data structures in static space so that they
+% won't move during GC.
+
+\cmucl{} supports calling Lisp from C via the \funref{def-callback}
+macro:
+
+\begin{defmac}{alien:}{def-callback}{\var{name} (\var{return-type}
+    \mstar{(arg-name arg-type)})}
+  This macro defines a Lisp function that can be called from C and a
+  Lisp variable.  The arguments to the function must be alien types,
+  and the return type must also be an alien type.  This Lisp function
+  can be accessed via the \funref{callback} macro.
+
+  \var{name} is the name of the Lisp function.  It is also the name of
+  a variable to be used by the \code{callback} macro.
+
+  \var{return-type} is the return type of the function.  This must be
+  a recognized alien type.
+
+  \var{arg-name} specifies the name of the argument to the function,
+  and the argument has type \var{arg-type}, which must be an alien type.
+\end{defmac}
+
+\begin{defmac}{alien:}{callback}{\var{callback-symbol}}
+  This macro extracts the appropriate information for the function
+  named \var{callback-symbol} so that it can be called by a C
+  function.  \var{callback-symbol} must be a symbol created by the
+  \code{def-callback} macro.
+\end{defmac}
+
+\subsection{Callback Example}
+
+Here is a simple example of using callbacks.
+\begin{lisp}
+(use-package :alien)
+(use-package :c-call)
+
+(def-callback foo (int (arg1 int) (arg2 int))
+  (format t "~&foo: ~S, ~S~%" arg1 arg2)
+  (+ arg1 arg2))
+
+(defun test-foo ()
+  (alien-funcall (sap-alien (callback foo) (function int int int))
+                 555 444444))
+\end{lisp}
+
+In this example, the callback function \code{foo} is defined which
+takes two C \code{int} parameters and returns a \code{int}.  As this
+shows, we can use arbitrary Lisp inside the function.
+
+The function \code{test-foo} shows how we can call this callback
+function from Lisp.  The macro \code{callback} extracts the necessary
+information for the callback function \code{foo} which can be
+converted into a pointer which we can call via \code{alien-funcall}.
+
+The following code is a more complete example where a foreign routine
+calls our Lisp routine.
+\begin{lisp}
+(use-package :alien)
+(use-package :c-call)
+
+(def-alien-routine qsort void
+  (base (* t))
+  (nmemb int)
+  (size int)
+  (compar (* (function int (* t) (* t)))))
+
+(def-callback my< (int (arg1 (* double))
+                       (arg2 (* double)))
+  (let ((a1 (deref arg1))
+        (a2 (deref arg2)))
+    (cond ((= a1 a2)  0)
+          ((< a1 a2) -1)
+          (t         +1))))
+
+(defun test-qsort ()
+  (let ((a (make-array 10 :element-type 'double-float
+                       :initial-contents '(0.1d0 0.5d0 0.2d0 1.2d0 1.5d0
+                                           2.5d0 0.0d0 0.1d0 0.2d0 0.3d0))))
+    (print a)
+    (qsort (sys:vector-sap a)
+           (length a)
+           (alien-size double :bytes)
+           (alien:callback my<))
+    (print a)))
+\end{lisp}
+
+We define the alien routine, \code{qsort}, and a callback, \code{my<},
+to determine whether two \code{double}'s are less than, greater than
+or equal to each other.
+
+The test function \code{test-qsort} shows how we can call the alien
+sort routine with our Lisp comparison routine to produce a sorted
+array.
 
 \subsection{Accessing Lisp Arrays}
 
-- 
GitLab