I'm rather new to using lisp and, of course, cffi. But, why not have someone pick cdecl or stdcall with as as option to load-library? Most libraries I have seen use one or the other, not both. Apparently, a lot of windows libraries liked to use stdcall for compatibility with Visual Basic and such ilk. Anything I can do to help? I'm a newbie, but good work ethic.....
-----Original Message----- From: cffi-devel-bounces@common-lisp.net on behalf of Luís Oliveira Sent: Tue 1/30/2007 1:52 AM To: CFFI Development List Subject: [cffi-devel] Extending defcfun and friends with extra options
Hello,
There are a couple of features people need -- namely stdcall and dll namespaces -- that depend on the ability to pass options to defcfun, foreign-funcall and defcallback. So we need to agree on a proper syntax to do this. Bonus points if we can get backwards compatibility.
This has been discussed in the past regarding defcfun but I forget what the conclusions were. Anyway, starting with the easiest:
(defcallback (foo :opt1 ... :opt2 ...) :rettype ((arg1 :type1) ...) body)
That seems to be the obvious place to put the options for defcallback. Any objections? defcfun, however, has some more possibilities:
;; #1 -- backwards compatible, similar to defcallback (defcfun (foo :opt1 ... :opt2 ...) :rettype (arg1 :type1) (arg2 :type2))
;; #2 -- backwards compatible, slightly funky syntax IMHO (defcfun foo :rettype (arg1 :type1) (arg2 :type2) :opt1 ... :opt2 ...)
;; #3 -- not backwards compatible, indentation looks odd when ;; there are no options present (defcfun foo :rettype ((arg1 :type1) (arg2 :type2)) :opt1 ... :opt2 ...)
IIRC, I used to be prefer option #3 because that way we could cleanly define the keyword arguments in the defcfun macro but lately I'm more inclined towards #1 since it indents better and the syntax is similar to defcallback. Also, #1 is backwards compatible; that's a plus, I guess. I think James used to prefer option #2. Is that still true? I don't completely dislike option #2.
And finally there's foreign-funcall. The syntax here should be pretty obvious too:
(foreign-funcall ("foo" :opt1 ... :opt2 ...) :type1 arg1 :type2 arg2 :rettype)
Except foreign-funcall also accepts a pointer, and in that case the first argument is evaluated (unlike the case where the argument is a string). I think (foreign-funcall ((some-form ...) :opt1 ... :opt2 ...) :type1 arg1 ... :rettype) looks a bit odd. Does that justify splitting such functionality off to another macro foreign-funcall-pointer with a different syntax? I think I'd rather avoid that.
Oh, and we need options for define-foreign-library too. Once again I'm thinking we should place the options in the name argument: (define-foreign-library (name :opt1 ... :opt2 ...) ...).
Comments and suggestions are most welcome.
On 30/01/07, Green Bryan - bgreen Bryan.Green@acxiom.com wrote:
[,,,] But, why not have someone pick cdecl or stdcall with as as option to load-library?
Doing that at runtime might not be straightforward as it implies recompiling all of the DEFCFUNs at library load time in order to have them match the appropriate calling convention.
Anyway, we can have this as an option for define-foreign-library:
(define-foreign-library (foo :general-opt1 ...) (:windows "foo.dll" :calling-convention :stdcall) (:unix "foo.so"))
At macroexpansion-time, this would set the :general-opt1 for foo always, and the :calling-convention only when cffi-features:windows is present in *features*, i.e. when you're compiling on a windows machine. (This, btw, would require slightly backwards incompatible adjustments to the syntax.)
Then you'd have:
(defcfun ("foo_function" :library foo) :rettype ...)
I've been thinking a little bit on how to best deduce the library when the :library option is not present (less typing for people that don't use bindings generators; also, see the other thread about DLL namespaces). The ideas I have for that so far are:
b) define-foreign-library option that associates a package with that library c) similar option that matches a prefix with the function name
I suppose these two could be used in conjunction. For instance, a function name would have to both be in package-foo and begin with "foo_" to be considered part of the foo library and inherit its options. In any case, the default would be the same no define-foreign-library options and no :library option means looking up the function names at library load time.
Re-reading what I just wrote makes me wonder whether this too much overkill just to avoid typing ":library foo" repeatedly.
Ah, I forgot about defcvar. (defcvar name type &key read-only-p) For consistency, I suppose we should put the options in the name argument but it already has keyword arguments.
;; #1 -- defcvar used to have that docstring argument ;; looks more like cl:defvar when no options are provided. (defcvar (name :opt1 ... :opt2 ...) :some-type "docstring here")
;; #2 -- cleaner, backwards-compatible (defcvar name :some-type :opt1 ... :opt2 ...)
I think I'm inclined towards #1.
Enough brain dumping for today.