Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

accessing Lisp values from C

14 views
Skip to first unread message

Schweiss Elsa

unread,
Apr 28, 1997, 3:00:00 AM4/28/97
to

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

Heiko Kirschke

unread,
Apr 29, 1997, 3:00:00 AM4/29/97
to

Schweiss Elsa <schw...@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: Heiko.K...@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

Erik Naggum

unread,
Apr 29, 1997, 3:00:00 AM4/29/97
to

* 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?

Heiko Kirschke

unread,
May 6, 1997, 3:00:00 AM5/6/97
to

Erik Naggum <er...@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 ...

0 new messages