Hi,
I saw some topics in the archives about varargs, but none answered how I might do this:
------------ xmlParserError (void *ctx, const char *msg, ...); ------------
SWIG (CFFI) produced this:
------------ (defcfun ("xmlParserError" xmlParserError) :void (ctx :pointer) (msg :string) (arg2 )) ------------
Is there any way I could use &rest here? or one big pointer? I don't quite know how to proceed...
Cheers, Brad
Brad Anderson brad@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 (,@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 writes:
Does anyone have an example where some sort of defcfun-varargs could actually be useful?
This could be useful for the Objective-C bridge:
;; Just tossing out ideas about syntax here... (defcfun ("objc_msgSend" send) id (object id) (method selector) &rest)
(send (find-objc-class "NSString") "stringWithUTF8String:" (:string :encoding :utf-8) "hi")
I think this could be pretty cool (modulo the arguments *rimshot* about the portability of calling varargs functions through FFI, of course..)
James