[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [spr1064] adjustable array from Lisp to C??
Date: Tue, 13 Feb 90 09:41:15 PST
From: klin@argon.berkeley.edu (Kuang-Kuo Lin)
I am trying to pass a string with variable size from Lisp to C,
and expect that C would change the value of the string.
In C, an array is simply treated as a pointer to the first element of
the array. In Lisp an array is an object with header information
which may include the size, adjustable flag, fill-pointer information,
etc.
When an array is passed to C through the foreign function interface,
only the pointer to the data block is passed. The other header
information is not readily available to the C program. Therefore, if
you want to change the fill-pointer or adjust the array, you can't do
that in C without going back into Lisp.
If you really do want to pass a string buffer from Lisp to C and have
C fill it, then you should create a simple-string (using MAKE-STRING)
with a size no smaller than the maximum amount that your C function
will want to write and pass that to C.
If, on the other hand, you are less concerned about having C overwrite
a lisp array, and just have your C function return its own array, you
can use the Allegro function FF:CHAR*-TO-STRING (I believe this
function started being available with Allegro 3.1). With this
function, you can just have your C function return a C string as an
integer (ie, pointer to the character array). Then FF:CHAR*-TO-STRING
will create a lisp string from that pointer. There is an inverse
function FF:STRING-TO-CHAR* that returns the integer to the beginning
of the data block in the Lisp string.
Finally, if you don't have FF:CHAR*-TO-STRING already in your Allegro,
you can use the following definition. It first determines the length
of the string, then allocates a Lisp string, and finally copies the
characters one-by-one. It is quite efficient in execution.
(defcstruct (c-string :malloc) (char 1 :char))
(defun char*-to-string (address)
"Create a Lisp string copy of a C string"
(declare (optimize (speed 3))
(integer address))
(if (eq 0 address)
(error "0 is not a valid character pointer"))
(let* ((length
(do* ((i 0 (1+ i))
(intchar (c-string-char address i)
(c-string-char address i)))
((eq 0 intchar) i)))
(string (make-string length)))
(declare (simple-string string)
(fixnum length i))
(do* ((i 0 (1+ i))
char)
((= i length))
(declare (optimize (safety 0))
(fixnum i)
(string-char char)
(simple-string str))
(setq char (code-char (c-string-char address i)))
(setf (schar string i) char))
string))
If you don't need to create a real Lisp array object and only need to
access the individual characters of the C string in place (the way C
itself does) the C-STRING-CHAR function defined by the DEFCSTRUCT is
all you need. It is setfable and very fast, since the compiler
opencodes it.
Charley
---
Charles A. Cox, Franz Inc. 1995 University Avenue, Suite 275
Internet: cox@franz.com Berkeley, CA 94704
uucp: uunet!franz!cox Phone: (415) 548-3600 FAX: (415) 548-8253