Subject: [clisp-list] Re: FFI and C-POINTERs

From: "Hoehle, Joerg-Cyril" <[email-masked]>
Date: Thu Aug 5 03:15:29 2004

Sam wrote:
>still, this is just access.  how does one _write_ to the memory
> returned by malloc?
Use C-Places, i.e. SETF. It seems you found out by yourself.
Or use (SETF (FOREIGN-VALUE #<FOREIGN-VARIABLE> x) on the objects.

>(let ((m (c-malloc 4)) ret)
>  (unwind-protect
>       (progn
>         (with-c-var (i '(c-ptr uint32) m)
>           (with-c-var (v '(c-ptr (c-array uint8 4)) m)
[...]
>*** - #<FOREIGN-ADDRESS #x003F6B98> cannot be converted to the foreign
>       type UINT32
>why uint32?! it's (c-ptr uint32)!

There's maybe a misconception here. The initarg to with-c-var is subject to conversion from Lisp to a foreign representation. Maybe this should be made explicit in the documentation.
E.g. for with-c-var (i '(c-pointer uint32) initarg) you need to supply a Lisp integer. You gave a #<foreign-address> instead.

The Lisp view doesn't care about pointers, therefore an initarg for uint32, (c-ptr uint32) or (c-ptr (c-ptr uint32)) is always a single Lisp integer value of type (unsigned-byte 32).

You can achieve what you maybe wished for like this:
  (with-c-var (i '(c-ptr uint32))
    (setf (cast i 'c-pointer) m)
    ;; a #<foreign-address> or <foreign-variable> is a correct initarg for the c-pointer type.
    (print i)
    (foo i)
    (setf i (bar))

BTW, what are you trying to achieve?

BTW2, I just inspected
http://clisp.cons.org/impnotes/dffi.html
and found that it doesn't mention FOREIGN-VALUE
It's the setf'able function to get/set values pointed to by #<FOREIGN-VARIABLE> objects. More manipulations are available via WITH-C-PLACE.

Regards,
	Jorg Hohle.

---

From: Sam Steingold <[email-masked]>
Date: Thu Aug 5 07:00:07 2004

> * Hoehle, Joerg-Cyril <[email-masked]> [2004-08-05 12:09:31 +0200]:
>

OK, thanks.

(let ((m (c-malloc 4)) ret)
  (unwind-protect
       (with-c-var (v '(c-ptr (c-array uint8 4)))
         (setf (cast v 'c-pointer) m)
         (with-c-var (i '(c-ptr uint32))
           (setf (cast i 'c-pointer) m)
           (setq i 0)
           (push v ret)
           (setq i (1- (ash 1 32)))
           (push v ret)
           (setq v #A((unsigned-byte 8) (4) (1 2 3 4)))
           (push i ret))
         (nreverse ret))
    (c-free m)))
(#A((unsigned-byte 8) (4) (0 0 0 0))
 #A((unsigned-byte 8) (4) (255 255 255 255))
 ;; the following depends on endianness
 #.(+ (ash 4 24) (ash 3 16) (ash 2 8) 1))

since here we see that the answer depends on endianness,
I propose adding :LITTLE-ENDIAN or :BIG-ENDIAN to *FEATURES*.

> BTW, what are you trying to achieve?
Pascal asked this first.

> BTW2, I just inspected http://clisp.cons.org/impnotes/dffi.html and
> found that it doesn't mention FOREIGN-VALUE It's the setf'able
> function to get/set values pointed to by #<FOREIGN-VARIABLE>
> objects. More manipulations are available via WITH-C-PLACE.

when is FOREIGN-VALUE useful?  why is it exported?
i.e., i know that is it used behind the scenes in WITH-C-PLACE,
WITH-C-VAR, DEF-C-VAR, ELEMENT, DEREF, SLOT, CAST, OFFSET, C-VAR-OBJECT,
C-VAR-ADDRESS, TYPEOF, SIZEOF, BITSIZEOF, but when is it used standalone?

as for compile-time type parsing, why not use

(define-compiler-macro parse-c-type (typespec &optional (name nil) &whole form)
  (if (constantp typespec)
      (parse-c-type typespec name) ; parse at compile time
      form)) ; decline: parse at run time

-- 
Sam Steingold (http://www.podval.org/~sds) running w2k
<http://www.camera.org> <http://www.iris.org.il> <http://www.memri.org/>
<http://www.mideasttruth.com/> <http://www.honestreporting.com>
A slave dreams not of Freedom, but of owning his own slaves.