Hi.
In the thread starting in:
http://common-lisp.net/pipermail/cl-opengl-devel/2009-June/000585.html
someone described problems running some CL-OPENGL GLUT examples in Clozure CL on Win32.
I'm not sure if this is the only problem, but it seems that the most functions defined in the FreeGLUT library use the 'stdcall' calling convention (a "Pascal"-like calling sequence where the callee is responsible for discarding args from the stack, sometimes used on Win32 for no obvious reason besides backward compatibility ...) and it seems reasonable to assume that it expects user-defined functions that it calls to follow this convention as well.
Because of implementation arcana, CCL doesn't really care whether a foreign function that it calls follows 'stdcall' or 'cdecl' conventions. The caller of a callback function (defined via CCL:DEFCALLBACK or the CFFI equivalent) may very well care, and the callback machinery has to be told which conventions to follow.
A callback function that accepts two 'int' arguments and returns their sum as an 'int' would be defined in CCL as:
(ccl:defcallback add-two-ints (:int x :int y :int) ;; The arglist declares X and Y to be C ints and that the function returns ;; a value of type 'int'. (+ x y))
That makes the value of ADD-TWO-INTS a foreign pointer to foreign-callable code that ultimately just adds a couple of signed 32-bit integers. By default, the glue code that handles the transition from C to lisp and back again when this function is called from foreign code assumes that pretty standard C calling conventions are being followed (all args are passed on the stack and left there when the callee returns, with a possible exception involving the invisible argument used to effect structure return.)
If we wanted to define a callback that followed 'stdcall' conventions, we can do so by prepending the keyword :DISCARD-STACK-ARGS to the callback's argument list:
(ccl:defcallback stdcall-add-two-ints (:discard-stack-args :int x :int y :int) ;; note that there's just a :DISCARD-STACK-ARGS keyword at the front of the ;; arglist, not a key/value pair (+ x y))
I'm fairly sure that the runtime effects of :DISCARD-STACK-ARGS will only occur on Win32 (e.g., that it's a no-op on other platforms).
I'd assume that anyone who's:
a) more familiar with CFFI than I am and b) less lazy than I am
can add support for stdcall-style callbacks to CFFI's OpenMCL/CCL-backend code, and doing so might help to get things like CL-OPENGL working on CCL/win32.
If anyone has any questions abou the CCL side of this, I'd be glad to try to answer them.
It looks like CFFI is generally familiar with this cdecl/stdcall stuff and has the infrastructure in place to do the right thing, but the CCL backend just doesn't implement it.
On Thu, Jun 4, 2009 at 10:59 AM, Gary Byers gb@clozure.com wrote:
I'm not sure if this is the only problem, but it seems that the most functions defined in the FreeGLUT library use the 'stdcall' calling convention
That shouldn't be a problem because CL-GLUT assumes a cdecl freeglut.dll and doesn't specify :cconv :stdcall for the callbacks it sets up. (And it works on other Lisps, hopefully not out of sheer luck.)
I'm pretty sure that FreeGLUT can be built using cdecl instead of stdcall and that I built one myself (http://common-lisp.net/~loliveira/tmp/freeglut.dll) but that was a while ago so I might be misremembering it.
It looks like CFFI is generally familiar with this cdecl/stdcall stuff and has the infrastructure in place to do the right thing, but the CCL backend just doesn't implement it.
Correct. I just pushed a patch that implements that. I couldn't test it because I don't have access to a Windows system at the moment so if anyone is interested, please load the test suite, after compiling libtest.c manually since cffi-tests.asd doesn't do that automatically on Windows, and run (rt:do-test 'cffi-tests::callbacks.stdcall.1).