1.4 The Module's Method Table and Initialization Function
Keywords: ext

#
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},
          ...
          {NULL,      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:

      void
      initspam()
      {
          (void) Py_InitModule("spam", SpamMethods);
      }

Note that for C++, this method must be declared `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.