Subject: [clisp-list] Question about begin_callback()/end_callback()

From: "Hoehle, Joerg-Cyril" <[email-masked]>
Date: Mon Nov 11 04:38:03 2002

Dan Stanger wrote:
>The flow of control is roughly:
>create window which enters a microsoft dll.
>windowproc my subroutine which is called by the microsoft dll
>funcall which calls the lisp oncreate function.
>
>The funcall causes the lisp stack overflow.
>
>Do I need to add a begin_callback()/end_callback() around the funcall?

Yes, not only around the funcall, but as soon as you do anything with the lisp world, e.g. pushSTACK() prior to the funcall etc.

If the callback is a Lisp function (typically obtained when passing a Lisp function as argument via the FFI), begin/end_callback() is taken care of for you in src/foreign.d:callback() and by the CLISP compiler of DEF-CALL-IN forms.

The explicit begin/end_callback() is needed if you write C (glue) code and access (or call) some Lisp data from there.

BTW, why don't you let the FFI build the callback for you, if all you do anyway is call a Lisp function?

>(gdi::initc *functions* #'onCreate)
You didn't show initc's signature, but it looks like a foreign function. If it is such, depending on the signature, it receives the parameter f as a pointer to a (C-style trampoline) function (and *not* as a pointer to a Lisp function object). See also src/foreign.d:convert_function_to_foreign().

Therefore, the way to call it (from C) is not via funcall, but using C call style.

E.g.
>     pushSTACK(allocate_fpointer(hWnd));
>     funcall(O(onCreate),1); // fails in this call
seems wrong.
Instead you can use
  void (*onCreate)(WINDOWS_HANDLE h); /* as a C variable */
     /* 1 argument callback */
in initc: onCreate = (cast) (second argument value);
and in the C part of the callback:
  (*onCreate)(hWnd);

Or you can invoke convert_function_to_foreign() and also free_foreign_callin() on your own. Sadly, these are not exported from foreign.d (at least in 2.28).

NB: You must create callback objects (i.e. trampolines) if you expect to create callbacks to Lisp on your own! The reason is that the address of actual Lisp function changes via GC and the begin/end_callback() stuff. The trampoline machinery in foreign.d and ffcall/ is explicitly there for this purpose (and maintains a mapping from fixed addresses to moving Lisp functions).

Did that help?

Regards,
	Jorg Hohle.