with-foreign-object wrapper, extra indirection & need of CMUCL's ADDR operator

"Hoehle, Joerg-Cyril" <[email protected]> Fri, 22 Mar 2002 13:17:15 +0100
Newsgroups gmane.lisp.uffi.general
Message-ID <[email protected]>
Hi,

First, I believe a WITH- form for (hopefully) stack allocation is a good thing to have (useful level of abstraction and flexibility).

> (defun gethostname2 ()
>   "Returns the hostname"
>   (uffi:with-foreign-object (name (:array :unsigned-char 256))
>     (if (zerop (c-gethostname (uffi:char-array-to-pointer name) 256))
>         (uffi:convert-from-foreign-string name)
>         (error "gethostname() failed."))))

> doing this for CMUCL is that objects are quite a bit different when
> allocated with make-alien vs. with-alien. There is basically an extra 
> level of indirection with make-alien.

To be explicit about CMUCL for people who don't know (please ignore typos):
(with-alien ((name (array (unsigned 8) 256)))
  (alien-funcall
   (extern-alien "gethostname"
     (function integer (* (array (unsigned 8) 256)) integer))
   (ADDR name) 256)) ; pointer to array is passed
    ^^^^ unlike C, where & of an array is implicit
Whereas with MAKE-ALIEN made dynamic objects, ADDR is not suitable since we already have a pointer to the memory.

I hope that appropriate use of MACROLET or symbol-macros for the names defined via WITH-* (e.g. NAME) can help solve these issues.


> This indirection consistent is
> the other implementations.
I don't understand the grammar of the last sentence?


> At this point, I'm not sure how cleanly I can
> use CMUCL stack allocation and still keep pointer references 
> consistent
> with make-alien objects and with objects in other implementations.

If I understand you right, I believe the exact same problem would occur with the extension to CLISP that I'm currently thinking about: adding alloc+free!
(FOREIGN-ALLOC (ARRAY uint8 256) &optional init)
yields a foreign variable object. A foreign variable is a typed pointer (a tuple of an address and a foreign type), I believe similar to what LispWorks provides.

This Lisp object embodies an indirection, since its address part is a reference to the actual array bytes.

So a foreign function that uses this array would of course have to be declared as (name (* (array uint8 256))).
                   ^^
Voila, the extra level of indirection I believe you talk about.

Regards,
	Jorg Hohle.