[cffi-devel] Re: varargs (again)

Luís Oliveira luismbo at gmail.com
Fri Jan 13 03:00:50 UTC 2006


Brad Anderson <brad at sankaty.com> writes:
> (defcfun ("xmlParserError" xmlParserError) :void
>   (ctx :pointer)
>   (msg :string)
>   (arg2 ))

This is obviously broken.


> Is there any way I could use &rest here?  or one big pointer?
> I don't quite know how to proceed...

Right now, you'll have to use foreign-funcall to use this function but I
suppose we could come up with some sort of mechanism to define vararg
functions.

  * (defcfun-varargs "printf" :int (control :string))

  PRINTF
  * (printf (format nil "hello variadic %s! %d~%") :string "world" :int 42)
  hello variadic world! 42

  25


What do you think of an interface like this? Possibly something like
this would be better?

  (defcfun-varargs "printf" :int (constrol :string) (&rest args))


Also, maybe defcfun* would be a better name? Or even make defcfun
recognize the (&rest ...) token? Here's a first try at this possible
interface, in case you want to play with it:

  (in-package :cffi)

  (defmacro defcfun-varargs (name return-type &body args)
    "Defines a Lisp macro that expands into a foreign-funcall calling a
  varargs foreign function."
    (discard-docstring args)
    (with-unique-names (varargs)
      (let ((lisp-name (lisp-function-name name))
            (foreign-name (foreign-function-name name))
            (arg-names (mapcar #'car args)))
        `(defmacro ,lisp-name (, at arg-names &rest ,varargs)
           `(foreign-funcall ,',foreign-name
                             ,@,`(list ,@(loop for pair in args
                                               collect (second pair)
                                               collect (first pair))) 
                             ,@,varargs
                             ,',return-type)))))


Using this macro you would do something like this:

  (defcfun-varargs ("xmlParserError" xml-parser-error) :void
    (ctx :pointer)
    (msg :string))

  (xml-parser-error some-ctx "error number: %d" 42)


But, this is a bad example. In this case, I suppose what you really
should do is probably something like this:

  (defcfun "xmlParserError" :void
    (ctx :pointer)
    (msg :string))

  (defun xml-parser-error (control-string &rest args)
    (xmlParserError <whatever-a-ctx-is>
                    (format nil "~?" control-string args)))

  (xml-parser-error "error number: ~A" 42)


Does anyone have an example where some sort of defcfun-varargs could
actually be useful?

-- 
Luís Oliveira
luismbo (@) gmail (.) com
Equipa Portuguesa do Translation Project
http://www.iro.umontreal.ca/translation/registry.cgi?team=pt




More information about the cffi-devel mailing list