From: Hoehle, Joerg-C. <Joe...@t-...> - 2006-11-08 15:29:17
|
Hi, [I'm taking this to clisp-list since 1. that's where most discussions = about gtk take place right now, 2. it's open without prior subscription = and 3. the def-call-in issue is of general interest.] Jim Bailey wrote: >There is no gtk_cleanup() in gtk, that is the name of the function we >should be making available as a c callback (the name is not important, >maybe it could be made more obvious that it is a clisp side thing, >maybe gtk-cleanup-callback). >My use of def-call-in is probably wrong, I just wanted a lisp function >that I could pass as a function pointer to g_signal_connect_data, and >not incur any memory allocation each time I did this. I presume that >what I should have done is just write a normal lisp function and use >that. Indeed, there's some harmless misconception. See below. > Will the ffi reuse the same generated stub for a function (as >opposed to a closure), or is there some otherway of allocating a >function pointer just once? A Lisp function (as opposed to closure)'s callback will be reused while = the foreign type declaration remains EQ. That's a big difference with = closures. Indeed there's a misconception about use of def-call-in present in the = code, both in gtk-cleanup and gtk-callback-N. DEF-CALL-IN generates nice small C stubs to invoke a Lisp function (with = lower overhead than a regular FFI call). Alas, these stubs are not used in gtk.lisp! When the Lisp code passes = #'gtk-cleanup or #',cb-name to a foreign function, it's an FFI generated = trampoline that is created to call the Lisp function -- much like the = already existing stub would do. I.e. def-call-in is currently superfluous. Alternatively, the C functions could be declared both DEF-CALL-IN and = DEF-CALL-OUT! call-in: The former generates the stub, call-out: the latter makes the stub accessible as a *unique* = #<FOREIGN-FUNCTION> object on the Lisp side. Then gtk.lisp can call = e.g. gtk-connect and pass this function pointer, without ever creating = another callback object. The callback is already in the gtk.c file, = created from the call-in definition. Advantages: a) passing a #<FOREIGN-FUNCTION> is faster than going through the = "lookup (or possibly create) callback object for this Lisp function" = code. b) the generated stub is faster at calling the Lisp function than the = callback. The stub does hardly use the FFI, while the callback needs = all of ffcall's trampoline, vacall and the foreign type must be parsed = at run-time. The automatically generated stub may look like this: int stub (int foo); { begin_callback(); // also in trampoline pushSTACK(int2I(foo)); lret =3D funcall(lisp_function,1); // call with one argument cret =3D I2int(lret); end_callback(); return cret; } The overhead of interpretation of the foreign function type has been = eliminated via direct compilation. (Actually, the current situation is = not that ideal: the stub calls instead = pushSTACK(convert_from_foreign(`ffi::int`)) instead of int2I(), and = vice-versa. Sam Steingold would say: of course, http://www.cygwin.com/acronyms/#PTC Impnotes does not explain that DEF-CALL-IN creates a C stub of the given = name during file-compilation. That would be valuable information. Summary: gtk.lisp should use (def-call-in callback0 (:name "gtk_lisp_callback0")) ; create C stub (def-call-out gtk-callback-0-arg (:name "gtk_lisp_callback0")) ; obtain = Lisp handle to that C stub and pass #'gtk-callback-0-arg (a #<FOREIGN-FUNCTION, not a pure Lisp = function) to gtk_signal_connect. It should *not* pass #'callback0 (a regular Lisp function). While this = works (this is what's currently done in gtk.lisp, after all), it a) does = not use the call-in and b) has more run-time overhead. BTW, I'm still not happy with the callback situation in the module. A = priori, the callbacks can take either scalar or pointer arguments, and = return similarly. The current code does not handle that. I've read = python-gtk can handle all forms. There's no reason Lisp cannot, but = I've yet to find good documentation on the gtk callback mechanism and = the meaning and use of the different slots of the SignalQuery structure = etc. or the source to python-gtk (or tcl-gtk or whatever). Regards, J=F6rg H=F6hle. |