[comp.lang.lisp.franz] Calling LISP functions from C.

dickinsn@cs.unm.edu (Emily G. Dickinson) (05/09/91)

I'm using allegrom cl on SUN4 and would appreciate sample
code from anyone who has succeeded in calling lisp
functions from C programs.

Thanks,
Emily Dickinson, University of New Mexico

rbj@uunet.UU.NET (Root Boy Jim) (05/10/91)

dickinsn@cs.unm.edu (Emily G. Dickinson) writes:
?I'm using allegrom cl on SUN4 and would appreciate sample
?code from anyone who has succeeded in calling lisp
?functions from C programs.

I think that I shall never see
a LISP function that's called from C.

?Thanks,
?Emily Dickinson, University of New Mexico
-- 
		[rbj@uunet 1] stty sane
		unknown mode: sane

rapo@cs.cornell.edu (Andy Rapo) (05/10/91)

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

gold@sgi.com (Michael Gold) (05/11/91)

In article <132261@uunet.UU.NET> rbj@uunet.UU.NET (Root Boy Jim) writes:
>I think that I shall never see
>a LISP function that's called from C.
>

Perhaps somebody can clarify this point, but I believe you *can* call a
lisp function from C, assuming the C function is called from the lisp
process...

--
    Michael I. Gold	 	You go your way, I'll go mine,
    Silicon Graphics Inc.	I don't care if we get there on time,
    Internet: gold@sgi.com	Everybody's searching for something they say,
    Voice: (415) 335-1709	I'll get my kicks on the way...

cccstevn@dino.ucdavis.edu (Steve Ansell) (05/11/91)

In article <1991May10.202942.1569@odin.corp.sgi.com> gold@sgi.com (Michael Gold) writes:
>In article <132261@uunet.UU.NET> rbj@uunet.UU.NET (Root Boy Jim) writes:
>>I think that I shall never see
>>a LISP function that's called from C.
>>
>
>Perhaps somebody can clarify this point, but I believe you *can* call a
>lisp function from C, assuming the C function is called from the lisp
>process...
>

I beleive that this posting was in response to the fact that the person who
asked the original question about calling Lisp from C had a signature of
"Emily Dickinson".  The above is a parody of one of her poems.  In other
words it was a joke ;-)

-- 
						-Steven T. Ansell
						Unix Consultant
						Computing Services U.C.D.

gold@sgi.com (Michael Gold) (05/12/91)

In article <12931@aggie.ucdavis.edu> cccstevn@dino.ucdavis.edu (Steve Ansell) writes:
>I beleive that this posting was in response to the fact that the person who
>asked the original question about calling Lisp from C had a signature of
>"Emily Dickinson".  The above is a parody of one of her poems.  In other
>words it was a joke ;-)
>

Sorry, I only open my mouth to change feet.  :-q

--
    Michael I. Gold	 	You go your way, I'll go mine,
    Silicon Graphics Inc.	I don't care if we get there on time,
    Internet: gold@sgi.com	Everybody's searching for something they say,
    Voice: (415) 335-1709	I'll get my kicks on the way...

dak@sq.sq.com (David A Keldsen) (05/14/91)

cccstevn@dino.ucdavis.edu (Steve Ansell) writes:

>In article <1991May10.202942.1569@odin.corp.sgi.com> gold@sgi.com (Michael Gold) writes:
>>In article <132261@uunet.UU.NET> rbj@uunet.UU.NET (Root Boy Jim) writes:
>>>I think that I shall never see
>>>a LISP function that's called from C.

>>Perhaps somebody can clarify this point, but I believe you *can* call a
>>lisp function from C, assuming the C function is called from the lisp
>>process...

>I beleive that this posting was in response to the fact that the person who
>asked the original question about calling Lisp from C had a signature of
>"Emily Dickinson".  The above is a parody of one of her poems.  In other
>words it was a joke ;-)

Unfortunately, the parodied poem is by...Joyce Kilmer.

Yet another example of a beautiful hypothesis slain by an ugly fact.  ;-)

(There should be an example in the manual on how to call Franz Lisp
functions from C; alas, it has been many a year since I saw the manual,
and my recollection is foggy...roughly, you need to get back in to the
"Franz machine" (via a function call) with a representation of a Lisp
function, its arguments, and the appropriate environment.)

(The LISP creeps in on little cat's parentheses...)

[Well, Robert Frost also lived in Amherst, Massachusetts, so it's a bit closer.]

Dak
-- 
David A. 'Dak' Keldsen of SoftQuad, Inc. email: dak@sq.com  phone: 416-963-8337
"You'd better get on with it," she said.  "That's fifty green fires and hot
leads to go, with a side order for blisters and scorpions.  Hold the mercy."
	-- _Sourcery_ by Terry Pratchett