Registering Callback Handler Objects
In the embedding examples thus far, C has been running and calling Python code from
a standard main program flow of control. Things are not always so simple, though; in
some cases, programs are modeled on an event-driven architecture in which code is
executed only in response to some sort of event. The event might be an end user clicking
a button in a GUI, the operating system delivering a signal, or simply software running
an action associated with an entry in a table.
In any event (pun accidental), program code in such an architecture is typically struc-
tured as callback handlers—units of code invoked by event-processing dispatch logic.
It’s easy to use embedded Python code to implement callback handlers in such a system;
in fact, the event-processing layer can simply use the embedded-call API tools we saw
earlier in this chapter to run Python handlers.
The only new trick in this model is how to make the C layer know what code should
be run for each event. Handlers must somehow be registered to C to associate them
with future events. In general, there is a wide variety of ways to achieve this code/event
association. For instance, C programs can:
- Fetch and call functions by event name from one or more module files
- Fetch and run code strings associated with event names in a database
- Extract and run code associated with event tags in HTML or XML
- Run Python code that calls back to C to tell it what should be run
And so on. Really, any place you can associate objects or strings with identifiers is a
potential callback registration mechanism. Some of these techniques have advantages
all their own. For instance, callbacks fetched from module files support dynamic re-
loading (imp.reload works on modules but does not update objects held directly). And
none of the first three schemes require users to code special Python programs that do
nothing but register handlers to be run later.
It is perhaps more common, though, to register callback handlers with the last
approach—letting Python code register handlers with C by calling back to C through
extension interfaces. Although this scheme is not without trade-offs, it can provide a
natural and direct model in scenarios where callbacks are associated with a large num-
ber of objects.
For instance, consider a GUI constructed by building a tree of widget objects in Python
scripts. If each widget object in the tree can have an associated event handler, it may
be easier to register handlers by simply calling methods of widgets in the tree. Associ-
ating handlers with widget objects in a separate structure such as a module file or an
XML file requires extra cross-reference work to keep the handlers in sync with the tree.
In fact, if you’re looking for a more realistic example of Python callback handlers,
consider the tkinter GUI system we’ve used extensively in this book. tkinter uses both
1530 | Chapter 20: Python/C Integration