It is important not to be impressed by the size and complexity of the average extension module; much of this is straightforward `boilerplate' code (starting right with the copyright notice)!
Let's skip the boilerplate and have a look at an interesting function
in `posixmodule.c
' first:
static object * posix_system(self, args) object *self; object *args; { char *command; int sts; if (!getargs(args, "s", &command)) return NULL; sts = system(command); return mkvalue("i", sts); }
This is the prototypical top-level function in an extension module. It will be called (we'll see later how) when the Python program executes statements like
>>> import posix >>> sts = posix.system('ls -l')
There is a straightforward translation from the arguments to the call
in Python (here the single expression 'ls -l'
) to the arguments that
are passed to the C function. The C function always has two
parameters, conventionally named self and args. The
self argument is used when the C function implements a builtin
method - this is advanced material and not covered in this document.
In the example, self will always be a NULL
pointer, since
we are defining a function, not a method (this is done so that the
interpreter doesn't have to understand two different types of C
functions).
The args parameter will be a pointer to a Python object, or
NULL
if the Python function/method was called without
arguments. It is necessary to do full argument type checking on each
call, since otherwise the Python user would be able to cause the
Python interpreter to `dump core' by passing invalid arguments to a
function in an extension module. Because argument checking and
converting arguments to C are such common tasks, there's a general
function in the Python interpreter that combines them:
getargs()
. It uses a template string to determine both the
types of the Python argument and the types of the C variables into
which it should store the converted values. (More about this later.)
If getargs()
returns nonzero, the argument list has the right
type and its components have been stored in the variables whose
addresses are passed. If it returns zero, an error has occurred. In
the latter case it has already raised an appropriate exception by so
the calling function should return NULL
immediately - see the
next section.