1.4 The Module's Method Table and Initialization Function
I promised to show how spam_system() is called from Python
programs. First, we need to list its name and address in a ``method table'':
static PyMethodDef SpamMethods[] = {
...
{"system", spam_system, METH_VARARGS,
"Execute a shell command."},
...
{NULL, NULL, 0, NULL} /* Sentinel */
};
Note the third entry ("METH_VARARGS"). This is a flag
telling the interpreter the calling convention to be used for the C function. It should
normally always be "METH_VARARGS" or "METH_VARARGS
| METH_KEYWORDS"; a value of 0 means that an obsolete variant of PyArg_ParseTuple() is used.
When using only "METH_VARARGS", the function should expect
the Python-level parameters to be passed in as a tuple acceptable for parsing via PyArg_ParseTuple(); more information on this function is provided
below.
The METH_KEYWORDS bit may be set in the third field if keyword
arguments should be passed to the function. In this case, the C function should accept a third
"PyObject *" parameter which will be a dictionary of keywords.
Use PyArg_ParseTupleAndKeywords() to parse the arguments to such a
function.
The method table must be passed to the interpreter in the module's initialization function.
The initialization function must be named initname(),
where name is the name of the module, and should be the only non-static item defined in the module file:
PyMODINIT_FUNC
initspam(void)
{
(void) Py_InitModule("spam", SpamMethods);
}
Note that PyMODINIT_FUNC declares the function as void return type, declares
any special linkage declarations required by the platform, and for C++ declares the function
as extern "C".
When the Python program imports module spam for the first time, initspam() is called. (See below for comments about embedding Python.)
It calls Py_InitModule(), which creates a ``module object'' (which
is inserted in the dictionary sys.modules under the key "spam"),
and inserts built-in function objects into the newly created module based upon the table (an
array of PyMethodDef structures) that was passed as its second
argument. Py_InitModule() returns a pointer to the module object
that it creates (which is unused here). It aborts with a fatal error if the module could not
be initialized satisfactorily, so the caller doesn't need to check for errors.
When embedding Python, the initspam() function is not called
automatically unless there's an entry in the _PyImport_Inittab table.
The easiest way to handle this is to statically initialize your statically-linked modules by
directly calling initspam() after the call to Py_Initialize()
or PyMac_Initialize():
int
main(int argc, char *argv[])
{
/* Pass argv[0] to the Python interpreter */
Py_SetProgramName(argv[0]);
/* Initialize the Python interpreter. Required. */
Py_Initialize();
/* Add a static module */
initspam();
An example may be found in the file Demo/embed/demo.c in the
Python source distribution.
Note: Removing entries from sys.modules
or importing compiled modules into multiple interpreters within a process (or following a fork() without an intervening exec()) can
create problems for some extension modules. Extension module authors should exercise caution
when initializing internal data structures. Note also that the reload()
function can be used with extension modules, and will call the module initialization function
(initspam() in the example), but will not load the module again if
it was loaded from a dynamically loadable object file (.so on Unix, .dll on Windows).
A more substantial example module is included in the Python source distribution as Modules/xxmodule.c. This file may be used as a template or simply read as
an example. The modulator.py script included in the source distribution
or Windows install provides a simple graphical user interface for declaring the functions and
objects which a module should implement, and can generate a template which can be filled in.
The script lives in the Tools/modulator/ directory; see the README file there for more information.
|