The Python binary library is usually what is physically embedded and linked in the C
program. The actual Python code run from C can come from a wide variety of sources:
- Code strings might be loaded from files, obtained from an interactive user at a
console or GUI, fetched from persistent databases and shelves, parsed out of
HTML or XML files, read over sockets, built or hardcoded in a C program, passed
to C extension functions from Python registration code, and so on. - Callable objects might be fetched from Python modules, returned from other
Python API calls, passed to C extension functions from Python registration code,
and so on. - Code files simply exist as files, modules, and executable scripts in the filesystem.
Registration is a technique commonly used in callback scenarios that we will explore
in more detail later in this chapter. But especially for strings of code, there are as many
possible sources as there are for C character strings in general. For example, C programs
can construct arbitrary Python code dynamically by building and running strings.
Finally, once you have some Python code to run, you need a way to communicate with
it: the Python code may need to use inputs passed in from the C layer and may want
to generate outputs to communicate results back to C. In fact, embedding generally
becomes interesting only when the embedded code has access to the enclosing C layer.
Usually, the form of the embedded code suggests its communication media:
- Code strings that are Python expressions return an expression result as their out-
put. In addition, both inputs and outputs can take the form of global variables in
the namespace in which a code string is run; C may set variables to serve as input,
run Python code, and fetch variables as the code’s result. Inputs and outputs can
also be passed with exported C extension function calls—Python code may use C
module or type interfaces that we met earlier in this chapter to get or set variables
in the enclosing C layer. Communications schemes are often combined; for in-
stance, C may preassign global names to objects that export both state and interface
functions for use in the embedded Python code.* - Callable objects may accept inputs as function arguments and produce results as
function return values. Passed-in mutable arguments (e.g., lists, dictionaries, class
instances) can be used as both input and output for the embedded code—changes
made in Python are retained in objects held by C. Objects can also make use of the
global variable and C extension functions interface techniques described for strings
to communicate with C.
- For a concrete example, consider the discussion of server-side templating languages in the Internet part of
this book. Such systems usually fetch Python code embedded in an HTML web page file, assign global
variables in a namespace to objects that give access to the web browser’s environment, and run the Python
code in the namespace where the objects were assigned. I worked on a project where we did something
similar, but Python code was embedded in XML documents, and objects that were preassigned to globals in
the code’s namespace represented widgets in a GUI. At the bottom, it was simply Python code embedded in
and run by C code.
Embedding Python in C: Overview| 1517