After a little wrestling with Verrazano I am now trying to port my existing OpenAL demo to use the CFFI bindings generated by VZN.
I got a couple of warnings from ACL:
Warning: :call-direct ignored; no argument types specified. ; While compiling (:TOP-LEVEL-FORM "openal-lib2.lisp" 10554) in C:\0dev\cl-openal\openal-lib2.lisp:
Why the Hell are they not reporting on which defun? I will go digging to see if I can find which, but it may not matter. Anyway, I took a look at the expansion of:
(cffi:defcfun ("alutUnloadWAV" alutunloadwav) alvoid (anonymous1 :int) (anonymous2 :pointer) (anonymous3 :unsigned-int) (anonymous4 :unsigned-int))
namely....
(PROGN (FF:DEF-FOREIGN-CALL (|%cffi-foreign-function/ALUTUNLOADWAV| "alutUnloadWAV") ((#:G1004 :INT INTEGER) (#:G1005 (* :VOID) INTEGER) (#:G1006 :UNSIGNED-INT INTEGER) (#:G1007 :UNSIGNED-INT INTEGER)) :RETURNING (:VOID NULL) :CALL-DIRECT T :ARG-CHECKING NIL :STRINGS-CONVERT NIL) (DEFUN ALUTUNLOADWAV (ANONYMOUS1 ANONYMOUS2 ANONYMOUS3 ANONYMOUS4) (CFFI::TRANSLATE-OBJECTS (#:G1000 #:G1001 #:G1002 #:G1003) (ANONYMOUS1 ANONYMOUS2 ANONYMOUS3 ANONYMOUS4) (:INT :POINTER :UNSIGNED-INT :UNSIGNED-INT) ALVOID (|%cffi-foreign-function/ALUTUNLOADWAV| #:G1000 #:G1001 #:G1002 #:G1003))))
I think there is a problem here in that the raw entry |%cffi-foreign-function/ALUTUNLOADWAV| is not really an inviting way to code raw calls to the API. Maybe I am wrong on this--perhaps the idea is that one would relatively rarely want to convert values explicitly and then call the raw function, so it is OK to make users write something like:
(defun alutunloadwav-raw (a1 a2 a3 a4) (|%cffi-foreign-function/ALUTUNLOADWAV a1 a2 a3 a4)
But is that raw name reliable between CFFI releases?
What I did with my FFI utils was reserve the C name for raw functions and use the Lispified name for functions which autoconverted parameters and return values. I also allowed for pre- and post-processing.
Kenny Tilton ktilton@nyc.rr.com writes:
I got a couple of warnings from ACL:
Warning: :call-direct ignored; no argument types specified. ; While compiling (:TOP-LEVEL-FORM "openal-lib2.lisp" 10554) in C:\0dev\cl-openal\openal-lib2.lisp:
Why the Hell are they not reporting on which defun? I will go digging to see if I can find which, but it may not matter.
That 10554 is probably the file position. Does Allegro's editor have a goto-char command?
I think there is a problem here in that the raw entry |%cffi-foreign-function/ALUTUNLOADWAV| is not really an inviting way to code raw calls to the API. Maybe I am wrong on this--perhaps the idea is that one would relatively rarely want to convert values explicitly and then call the raw function, so it is OK to make users write something like:
(defun alutunloadwav-raw (a1 a2 a3 a4) (|%cffi-foreign-function/ALUTUNLOADWAV a1 a2 a3 a4)
But is that raw name reliable between CFFI releases?
It is not inviting at all, nor is it reliable because only Allegro, Lispworks and Corman Lisp will have this "raw" function. The other lisps will have a call to %foreign-funcall inside the DEFUN.
In your particular example, since the types are built-in and don't have any translators, it doesn't a "raw" function is not necessary anyway since after macroexpansion the DEFUN looks something like this:
(defun alutunloadwav (anonymous1 anonymous2 anonymous3 anonymous4) (LET ((#:G1114 ANONYMOUS1)) (LET ((#:G1115 ANONYMOUS2)) (LET ((#:G1116 ANONYMOUS3)) (LET ((#:G1117 ANONYMOUS4)) (LET ((#:G1122 (|%cffi-foreign-function/ALUTUNLOADWAV| #:G1114 #:G1115 #:G1116 #:G1117))) #:G1122)))))
I have an idea to get rid of all those LETs by the way. (Is it worth the trouble though?)
The only advantage using |%cffi-foreign-function/ALUTUNLOADWAV| directly is that it would get inlined by Allegro's compiler. I suppose one could (declaim '(inline alutunloadwav)) though, that won't work in Allegro because its compiler ignore inline declarations, but it'll work in Lispworks. (this reminds me that CFFI should probably be inlining the raw function in Lispworks's case.)
Anyway, the problem really is that other Lisps won't have a raw function so I suppose the user should define a raw foreign function with DEFCFUN (ie. one with built-in types only, or other types which have no translators) if necessary.
What I did with my FFI utils was reserve the C name for raw functions and use the Lispified name for functions which autoconverted parameters and return values. I also allowed for pre- and post-processing.
Ah, how does this pre/post processing work in Hello-C? Does it allow for stuff CFFI's translators don't? Or is it more convinient?