arrays in CMUCL

Helmut Eller <e9626484-jqqTQQGuSV4hHGrKhHam0bNldLUNz+W/@public.gmane.org> Fri, 16 Aug 2002 16:59:50 +0200
Newsgroups gmane.lisp.uffi.general
Message-ID <[email protected]>
Hi,

I would like to write a binding for the pipe system call.  So, I
defined:

  (def-function ("pipe" c/pipe)
      ((fds (:array :int 2)))
    :returning :int)

And a wrapper like this:

(defun pipe ()
  (with-foreign-object (fds '(:array :int 2))
    (let ((status (c/pipe fds)))
      (ecase status
	(-1 (signal-posix-error))
	(0 (values (deref-array fds '(:array :int) 0)
		   (deref-array fds '(:array :int) 1)))))))

This works nice in Allegro, but in CMUCL I only get results like:

* (pipe)

#<Alien (array (alien:signed 32) 2) at #xBFFFF53C>
#<Alien (array (alien:signed 32) 2) at #xBFFFF544>


I investigated the WITH-FOREIGN-OBJECT macro a bit.  Apparently, the
problem stems from the conversion of the array to a pointer with
ALIEN:ADDR.  As a workaround, I modified WITH-FOREIGN-OBJECT so that
only non-array objects are converted to pointers:


(in-package :uffi)
(defmacro with-foreign-object ((var type) &rest body)
  #-(or cmu lispworks) ; default version
  `(let ((,var (allocate-foreign-object ,type)))
    (unwind-protect
	 (progn ,@body)
      (free-foreign-object ,var)))
  #+cmu
  (let ((obj (gensym))
	(type (eval type)))
    `(alien:with-alien ((,obj ,(convert-from-uffi-type type :allocate)))
      (let ((,var ,(if (and (consp type) 
			    (eq :array (car type)))
		       obj
		       `(alien:addr ,obj))))
	,@body)))
  #+lispworks
  `(fli:with-dynamic-foreign-objects ((,var ,(convert-from-uffi-type
					      (eval type) :allocate)))
    ,@body)
  )


Is there a better way to do this?

Regards,
Helmut