If you look closely, you may notice that I didn’t call putenv this time. It
turns out there’s good cause: the C library’s putenv wants a string of the
form “USER=Gilligan” to be passed, which becomes part of the envi-
ronment. In C code, this means we must create a new piece of memory
to pass in; we used malloc in Example 20-8 to satisfy this constraint.
However, there’s no simple and direct way to guarantee this on the Py-
thon side of the fence. In a prior Python release, it was apparently suf-
ficient to hold on to the string passed to putenv in a temporary Python
variable, but this no longer works with Python 3.X and/or SWIG 2.0. A
fix may require either a custom C function or SWIG’s typemaps which
allow its handling of data translations to be customized. In the interest
of space, we’ll leave addressing this as suggested exercise; see SWIG for
details.
Wrapping C++ Classes with SWIG
So far in this chapter, we’ve been dealing with C extension modules—flat function
libraries. To implement multiple-instance objects in C, you need to code a C extension
type, not a module. Like Python classes, C types generate multiple-instance objects and
can overload (i.e., intercept and implement) Python expression operators and type
operations. C types can also support subclassing just like Python classes, largely be-
cause the type/class distinction has largely evaporated in Python 3.X.
You can see what C types look like in Python’s own source library tree; look for the
Objects directory there. The code required for a C type can be large—it defines instance
creation, named methods, operator implementations, an iterator type, and so on, and
links all these together with tables—but is largely boilerplate code that is structurally
the same for most types.
You can code new object types in C manually like this, and in some applications, this
approach may make sense. But you don’t necessarily have to—because SWIG knows
how to generate glue code for C++ classes, you can instead automatically generate all
the C extension and wrapper class code required to integrate such an object, simply by
running SWIG over an appropriate class declaration. The wrapped C++ class provides
a multiple-instance datatype much like the C extension type, but it can be substantially
simpler for you to code because SWIG handles language integration details.
Here’s how—given a C++ class declaration and special command-line settings, SWIG
generates the following:
- A C++-coded Python extension module with accessor functions that interface with
the C++ class’s methods and members - A Python-coded module with a wrapper class (called a “shadow” or “proxy” class
in SWIG-speak) that interfaces with the C++ class accessor functions module
1502 | Chapter 20: Python/C Integration