Subject: FFI questions

From: [email-masked] (Joerg-Cyril Hoehle)
Date: Wed, 9 Aug 95 12:18:15 +0200

Hi,

I've a general question about FFI, not CLISP's FFI in particular.

I find it "good" (and fitting the Lisp paradigma) that a call to a C
functions that returns a string returns either a (LISP-)string or
NIL. Example: getenv().

Now consider a FFI where foreign pointers are simply represented as
integers (like in Franz, from what I know). Shall a function that
returns an opaque pointer return NIL or the integer 0 for C-NULL? Is
it "good" to make the NULL return value case render a separate type?

CMU (which has a distinguished foreign pointer type) doesn't make a
special case of NULL, and the only way to test for a NULL pointer is
to convert it to an integer first.

Should performance considerations come into play? (E.g. NIL is
probably easier to test than 0)

Should programming effort come into consideration? As an example, I find
(let (window)
  (unwind-protect
    (progn (setq window (openwindow 0-or-NIL? taglist))
       (when window
          ...))
    (when window (closewindow window))))
easier to write and read than
(let (window)
  (unwind-protect
    (progn (setq window (openwindow 0-or-NIL? taglist))
       (unless (zerop window)
          ...))
    (unless (and window (zerop window)) (closewindow window))))
or
(let ((window (openwindow 0-or-NIL? taglist)))
  (unwind-protect
    (unless (zerop window)
      ...)
    (unless (zerop window) (closewindow window))))
but the difference seems small and might be hidden inside a
foreign-null-p function call:
(defun foreign-null-p (p) (or (null p) (zerop p)))

Won't a NIL return affect portability for functions like sprintf()
which on some systems return the number of characters written and on
other return a buffer address because you don't know the prototype and
thus don't know whether 0 or NIL might be returned?

Are there more considerations to take into account than mentioned here?

Thanks for your thoughts on this topic,
 	Joerg Hoehle.
[email-masked]

---

From: [email-masked] (Bruno Haible)
Date: Wed, 9 Aug 95 18:21:58 +0200

> functions that returns a string returns either a (LISP-)string or

Agreed. This was done because the C type "char*" actually means
"either NULL or a pointer to a sequence of characters". The Lisp equivalent
of this is the type  (or null string).

> Shall a function that
> returns an opaque pointer return NIL or the integer 0 for C-NULL?

By definition, "opaque" means no conversion. CLISP boxes the pointer,
that's all. It never looks at the value of the pointer.

> easier to write and read ...

Agreed. Of course you can write a predicate `null-pointer-p', for example
like this:

  int foreign_null_p (pointer)
     void* pointer;
  { return (pointer == (void*)0); }

  (def-c-call-out null-pointer-p (:name "foreign_null_p")
                                 (:arguments (pointer c-pointer))
                                 (:return-type boolean)
  )

or by using EQUALP with a previously defined boxed NULL pointer.

In general, this is the way to go, because you will want more than
to look whether the pointer is NULL; for example, you may want to access
fields of the structure pointed to.

If you really want a special kind of argument and result converter for
nearly-opaque pointers, where the only conversion is for NULL, it is easy
to introduce a new converter, say C-POINTER-OR-NULL, similar to C-POINTER.

> thus don't know whether 0 or NIL might be returned?

To be portable, you have to specify the return type of sprintf() as
NIL (means "void") anyway.

Bruno Haible                        email: <[email-masked]>
Software Engineer                   phone: +33-1-49083585