From: Schweiss Elsa
Subject: accessing Lisp values from C
Date: 
Message-ID: <3364B7E6.41C6@lig.di.epfl.ch>
Hello,

I am working with Allegro CL 4.3 on Silicon Graphics machines and trying
to bind C program (called from ACL) with Lisp functions. I want to
access Lisp values from C program but I don't know what kind of value
the C function lisp_value() returns. How can I convert this returned
value to something meaningful?

This is my example :
---------------
lispprog.lsp contains :
(in-package "USER")

(unless (find-package "C")
  (defpackage "C")
  (load "bib.so")
)

#+mips #+allegro
(defmacro def-c-function (Name Type &rest args)
  `(ff::defforeign
     ',(symbol-from-string (string Name) 'c)
     :language :c
     :entry-point   ,(format nil "~a" Name)
     :return-type   ,(or type :integer)
     :arguments     ',args))

(defun symbol-from-string (string &optional (package *package*))
  (declare (type string string))
  (intern (string-upcase string) package))

(def-c-function "main" :integer ) 
(def-c-function "cfunction" :integer )

(ff::defun-c-callable lfunction ((x :signed-long))
  (format t "lisp function begins : ")
  (format t "parameter x = ~a / "x)
  (setq x 378)
  (ff::register-value x 8)
  (format t "registered value = ~a / "(ff::lisp-value 8))
  x
)
(ff::register-function 'lfunction 5)


prog.c contains :
#include "prog.h"
#include <stdio.h>

/*call to a registered Lisp function*/
long lisp_call1(int addr, int arg) 
{
  void *lisp_call_address();
  void (*lc)();
  long res;

  lc = lisp_call_address(addr);
  (*lc)(arg);
 
  return(res);
}

int cfunction ()
{
  long j;
  long C_res;

  j = lisp_call1(5,773);  /* CALL to the Lisp function */
  C_res=lisp_value(8);
  printf("C_res = %ld \n",C_res);
  return(0);
}

main()
{
  cfunction ();
  printf("End \n");
}

I compile in an unix shell with     cc -c prog.c
and then with             ld -shared -o bib.so prog.o
I start the ACL and 

USER(1):  (load "lien.lsp")
; Loading ./lien.lsp
;   Foreign loading ./bib.so.
T
USER(2): (c::main)
lisp function begins : parameter x = 773 / registered value = 378 /
C_res = 1512 
End 

0
USER(3): 
---------------

My problem is that lisp_value returns a different number than
the registered value in lisp (I noted that it is always multiplied
by four, but I am not sure). 

Thanks in advance. Elsa
--

ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo
Ing. student Elsa Schweiss, Computer Graphics Lab (LIG)
Swiss Federal Institute of Technology (EPFL),
CH-1015 Lausanne Switzerland
tel : +(41)(21) 693-6643    lab : +(41)(21) 693-5248
fax : +(41)(21) 693-5328    URL : http://ligwww.epfl.ch/~schweiss
ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo

From: Heiko Kirschke
Subject: Re: accessing Lisp values from C
Date: 
Message-ID: <uafminxme.fsf@poet.de>
Schweiss Elsa <········@lig.di.epfl.ch> writes:

> I am working with Allegro CL 4.3 on Silicon Graphics machines and trying
> to bind C program (called from ACL) with Lisp functions. I want to
> access Lisp values from C program but I don't know what kind of value
> the C function lisp_value() returns. How can I convert this returned
> value to something meaningful?

Consult the file home/misc/lisp.h relative to the Allegro installation
directory. The Allegro foreign-function interface is a *little bit*
clumsy. The ff::register-value function ensures that the registered
LISP objects won't disappear after the next GC. If I remember right,
ff::register-function will return an unsigned long, which can be
casted in C to ( * fnLisp ) ( void ), i.e. a pointer to a procedure;
when fnLisp is called, the registered LISP function will be called
effectively.

What you get from lisp_value is the direct LISP object in its internal
Allegro representation. lisp.h tells you how to decode the arg on the
C side. The lower 3 (?) or 2 (?) bits of the value are used as tag
bits. When these bits are 0, the value must be interpreted as a
pointer to a memory-allocated area containing the (non-immediate) LISP
object. Very roughly, these are all objects requiring allocated
memory, like symbols, vectors, ...

When the tag bits are != 0, the value is an `immediate value', i.e. a
fixnum or a character, without any associated allocated memory.

> My problem is that lisp_value returns a different number than
> the registered value in lisp (I noted that it is always multiplied
> by four, but I am not sure). 

So your assumption that the value you receive from lisp_value on the C
side is the value put into the LISP side multiplied by 4 is correct;
to be exact, it is someting like <C value> := <LISP value> * 4 +
<fixnum tag bits value>. If you want to be sure that the LISP object
is really a fixnum, you've to check the tag bits (there are C macros
inside lisp.h for this named GetTag(x) or GetType(x)).

Viele Gruesse, Heiko
--
Heiko Kirschke             EMail: ··············@poet.de
POET Software GmbH         Web:   http://www.poet.de/
Fossredder 12              Tel:   +49 40 60990-263
D-22359 Hamburg            Fax:   +49 40 60990-115
From: Erik Naggum
Subject: Re: accessing Lisp values from C
Date: 
Message-ID: <3071291051192250@naggum.no>
* Heiko Kirschke
| What you get from lisp_value is the direct LISP object in its internal
| Allegro representation.  lisp.h tells you how to decode the arg on the C
| side.  The lower 3 (?) or 2 (?) bits of the value are used as tag bits.
| When these bits are 0, the value must be interpreted as a pointer to a
| memory-allocated area containing the (non-immediate) LISP object.  Very
| roughly, these are all objects requiring allocated memory, like symbols,
| vectors, ...
| 
| When the tag bits are != 0, the value is an `immediate value', i.e. a
| fixnum or a character, without any associated allocated memory.

wrong!  please be careful with the details when you give such advice.  all
of this is easy to understand from actually inspecting lisp.h.

Allegr CL (the real thing, for Unix) uses three tag bits on most
architectures.  0 is even integer and 4 is odd integer (effectively giving
29-bit signed fixnums).  all other tags effectively cause the object to be
offset somewhat from the pointer.  e.g., a cons may have tag 1 and thus you
find the CAR on the address having a numeric value one less than the
pointer. and the CDR on the address three bytes up.  if you can align all
objects on word boundaries, and all allocation on 8-byte boundaries, and
you have a CPU that can do indexing on registers before access, you lose
exactly nothing in performance, and win the ability to use hardware traps
for unaligned memory access in the process.

| > My problem is that lisp_value returns a different number than
| > the registered value in lisp (I noted that it is always multiplied
| > by four, but I am not sure). 
| 
| So your assumption that the value you receive from lisp_value on the C
| side is the value put into the LISP side multiplied by 4 is correct; to
| be exact, it is someting like <C value> := <LISP value> * 4 + <fixnum tag
| bits value>.

yet, to be _exact_, it is multiplied by four (left-shifted two bits), and
that's all there is to it.  one some architectures, having the lower two
bits zero in integers also makes a number of interesting instructions
available.

note that this is the usual way to deal with tags on byte-adressable CPU's
with alignment constraints.

#\Erik
-- 
if we work harder, will obsolescence be farther ahead or closer?
From: Heiko Kirschke
Subject: Re: accessing Lisp values from C
Date: 
Message-ID: <uyb9t11zb.fsf@poet.de>
Erik Naggum <····@naggum.no> writes:

> Allegr CL (the real thing, for Unix) uses three tag bits on most

Well, I'm not so sure. The MOP is very ok, but the foreign-function
interface needs some work ...

Viele Gruesse, Heiko
--
Heiko Kirschke             EMail: ··············@poet.de
POET Software GmbH         Web:   http://www.poet.de/
Fossredder 12              Tel:   +49 40 60990-263
D-22359 Hamburg            Fax:   +49 40 60990-115