Article View: comp.lang.lisp.franz
Article #25Re: Calling LISP functions from C.
From: Andy Rapo
Date: Fri, 10 May 1991 15:34
Date: Fri, 10 May 1991 15:34
111 lines
4379 bytes
4379 bytes
Emily,
I've been doing a lot of C/Lisp interfacing lately with
allegro. In order to call a lisp function from C, you need to load
the C code into your lisp image. Then you need to make your lisp
functions c-callable and register them with Lisp. Lisp stores a
pointer to the function in a table that C can access. If the
registered Lisp function moves, the pointer in the table is updated.
In this way, C can always find the Lisp function.
(defun-c-callable scale_z-callback (val)
(format t "This is Lisp called with value ~A. ~%" val))
(multiple-value-setq (*ptr1* *index1* *prev-ptr1*)
(register-function 'scale_z-callback))
*ptr1* is a pointer to the Lisp function. *index1* is an index into
the table of pointers. I haven't used *prev-ptr1* yet. *ptr1* is the
value you need for now.
You have to pass C the address of the Lisp function that you want to
call. The way I have done this is to set up a structure in C
that holds poiters to functions. In C the struct looks like this:
/* these are all pointer to functions that return int */
typedef struct ptr_type {
int (*scale_z)();
int (*scale_y)();
int (*scale_x)();
.
.
.
} ptr_type;
ptr_type ptr;
This C code would be in a file like c-interface.c. This file would be compiled and the resulting object file, c-interface.o, would be loaded into Lisp. More on this in a sec.
In order to assign values to members of the struct I make the struct
accessible to Lisp using the defcstruct function. This function makes
accessor functions for a c-struct.
;;; MAKE-PTR-STRUCT-ACCESSORS makes accessor functions which, when
;;; supplied with a pointer to a C struct, will return the value
;;; stored there. Setf can be used to modify the C struct. The C
;;; struct exists in C space and is not moved by Lisp garbage collection.
(defun make-ptr-struct-accessors ()
(defcstruct (ptr :malloc)
(scale_z :unsigned-long)
(scale_y :unsigned-long)
(scale_x :unsigned-long)
.
.
. ))
Then I can get the value of a c-struct member (i.e. scale_z) by typing
(ptr-scale_x *pointer-to-cstruct*).
These are like CLOS accessors.
I have to supply a pointer to the (ptr-scale_z ...)
function so that Lisp can find the c-struct. In C, I've defined the
following function which returns the address of the c-struct.
ptr_type *get_ptr_address()
{
return &ptr;
}
I make this function (and the other C objects I need) available to Lisp by loading the .o file that it is defined in.
(load "" :foreign-files '("c-interface.o")
:system-libraries '("m" "gl_s"))
Next I make Lisp aware of the newly loaded c function.
(defforeign 'get_ptr_address :arguments nil
:return-type :integer))
And then I call the c function, get_ptr_address, to get the address of
the c-struct, *ptr*, and use it with the Lisp accessor functions to get at the values of the c-struct.
;;; SET-PTR-STRUCT-ADDRESS sets *ptr* to be the address of the C
;;; struct which contains pointers to Lisp functions.
;;; These pointers are used by C to "callback" to Lisp.
(defun set-ptr-struct-address ()
(setf *ptr* (get_ptr_address)))
(defun set-callback-ptrs ()
(setf (ptr-scale_z *ptr*) *ptr1*))
Now, the c-struct member, ptr.scale_z, contains *ptr1* which is the
address of the Lisp function, scale_z-callback.
C can call this Lisp function like this:
(*ptr.scale_z)(val);
Whew....
Well, its actually very easy to do, and worth the effort. Interfacing
between C and Lisp can make life very easy for you later on. If you
have any questions let me know. As I said, I've been doing this a lot
lately and would be glad to share what I've learned.
Andrew Rapo
Cornell University
Simulation/Robotics
Technical Details
Message-ID:
<1991May10.153446.7573@cs.cornell.edu>Path:
arc1-ca.pugleaf.net!utzoo!utgpu!news-server.csri.toronto.edu!cs.utexas.edu!wuarchive!usc!rpi!batcomputer!cornell!cs.cornell.edu!rapoReferences:
<DICKINSN.91May8223931@pele.cs.unm.edu>Show Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!utzoo!utgpu!news-server.csri.toronto.edu!cs.utexas.edu!wuarchive!usc!rpi!batcomputer!cornell!cs.cornell.edu!rapo From: rapo@cs.cornell.edu (Andy Rapo) Newsgroups: comp.lang.lisp.franz Subject: Re: Calling LISP functions from C. Message-ID: <1991May10.153446.7573@cs.cornell.edu> Date: 10 May 91 15:34:46 GMT References: <DICKINSN.91May8223931@pele.cs.unm.edu> Sender: news@cs.cornell.edu (USENET news user) Distribution: comp.lang.lisp.franz Organization: Cornell University, CS Dept., Ithaca, NY Lines: 111 Nntp-Posting-Host: spinet.cs.cornell.edu