## 5 Callbacks

A callback declaration must include a parameter named “ID”. The ID argument will be used to find the Scheme callback procedure. It must be the same “user data” value provided to the toolkit when the callback was registered. For example, a callback trampoline named `Scm_delete_event` might be declared like this:

    (callback gint
              delete_event
              (window (* GtkWidget))
              (event (* GdkEventAny))
              (ID gpointer))

The callback might be registered with the toolkit like this:

    (C-call "g_signal_connect" window "delete_event"
            (C-callback "delete_event")     ; e.g. &Scm_delete_event
            (C-callback                     ; e.g. 314
              (lambda (window event)
                (C-call "gtk_widget_destroy" window)
                0)))

The toolkit’s registration function, `g_signal_connect`, would be declared like this:

    (extern void
            g_signal_connect
            (object (* GtkObject))
            (name (* gchar))
            (CALLBACK GtkSignalFunc)
            (ID gpointer))

This function should have parameters named `CALLBACK` and `ID`. The callout trampoline will convert the callback argument from a Scheme alien function to an entry address. The `ID` argument will be converted to a C integer and then cast to its declared type (in this example, `gpointer`).

Note that the registered callback procedures are effectively pinned. They cannot be garbage collected. They are “on call” to handle callbacks from the toolkit until they are explicitly de-registered. A band restore automatically de-registers all callbacks.

The callback procedures are executed like an interrupt handler. They actually interrupt the thread executing the most recent callout, e.g. to `gtk_main`. The thread runs with thread switching disabled for the duration of the callback, and can callout to the toolkit, which can callback again. The (nested) callbacks and nested callouts all run in the same thread, and so will return in LIFO order as expected by the toolkit. Note that the runtime system will not balk at a callback procedure that calls `yield-thread`, waits for I/O, sleeps, or otherwise causes a thread switch. Presumably such a procedure has some other way of enforcing the LIFO ordering.

The `outf-console` procedure is provided for debugging purposes. It writes one or more argument strings (and `write`s any non-strings) to the console and flushes, atomically, via a machine primitive, bypassing the runtime’s I/O buffering and thread switching. Thus multiple debugging trace messages arrive on the console intact and uninterrupted.