summaryrefslogtreecommitdiffstats
path: root/Doc
diff options
context:
space:
mode:
authorMartin v. Löwis <martin@v.loewis.de>2008-06-11 05:26:20 (GMT)
committerMartin v. Löwis <martin@v.loewis.de>2008-06-11 05:26:20 (GMT)
commit1a21451b1d73b65af949193208372e86bf308411 (patch)
tree8e98d7be9e249b011ae9380479656e5284ec0234 /Doc
parentcdf94635d7e364f9ce1905bafa5b540f4d16147c (diff)
downloadcpython-1a21451b1d73b65af949193208372e86bf308411.zip
cpython-1a21451b1d73b65af949193208372e86bf308411.tar.gz
cpython-1a21451b1d73b65af949193208372e86bf308411.tar.bz2
Implement PEP 3121: new module initialization and finalization API.
Diffstat (limited to 'Doc')
-rw-r--r--Doc/c-api/import.rst4
-rw-r--r--Doc/extending/extending.rst67
2 files changed, 44 insertions, 27 deletions
diff --git a/Doc/c-api/import.rst b/Doc/c-api/import.rst
index 6f6b4b8..fdbbb12 100644
--- a/Doc/c-api/import.rst
+++ b/Doc/c-api/import.rst
@@ -200,7 +200,7 @@ Importing Modules
tricks with this to provide a dynamically created collection of frozen modules.
-.. cfunction:: int PyImport_AppendInittab(char *name, void (*initfunc)(void))
+.. cfunction:: int PyImport_AppendInittab(char *name, PyObject* (*initfunc)(void))
Add a single module to the existing table of built-in modules. This is a
convenience wrapper around :cfunc:`PyImport_ExtendInittab`, returning ``-1`` if
@@ -221,7 +221,7 @@ Importing Modules
struct _inittab {
char *name;
- void (*initfunc)(void);
+ PyObject* (*initfunc)(void);
};
diff --git a/Doc/extending/extending.rst b/Doc/extending/extending.rst
index b4ac803..4af7168 100644
--- a/Doc/extending/extending.rst
+++ b/Doc/extending/extending.rst
@@ -191,21 +191,22 @@ usually declare a static object variable at the beginning of your file::
static PyObject *SpamError;
-and initialize it in your module's initialization function (:cfunc:`initspam`)
+and initialize it in your module's initialization function (:cfunc:`PyInit_spam`)
with an exception object (leaving out the error checking for now)::
PyMODINIT_FUNC
- initspam(void)
+ PyInit_spam(void)
{
PyObject *m;
- m = Py_InitModule("spam", SpamMethods);
+ m = PyModule_Create(&spammodule);
if (m == NULL)
- return;
+ return NULL;
SpamError = PyErr_NewException("spam.error", NULL, NULL);
Py_INCREF(SpamError);
PyModule_AddObject(m, "error", SpamError);
+ return m;
}
Note that the Python name for the exception object is :exc:`spam.error`. The
@@ -303,15 +304,26 @@ accept a third ``PyObject *`` parameter which will be a dictionary of keywords.
Use :cfunc:`PyArg_ParseTupleAndKeywords` to parse the arguments to such a
function.
-The method table must be passed to the interpreter in the module's
+The method table must be referenced in the module definition structure::
+
+ struct PyModuleDef spammodule = {
+ PyModuleDef_HEAD_INIT,
+ "spam", /* name of module */
+ spam_doc, /* module documentation, may be NULL */
+ -1, /* size of per-interpreter state of the module,
+ or -1 if the module keeps state in global variables. */
+ SpamMethods
+ };
+
+This structure, in turn, must be passed to the interpreter in the module's
initialization function. The initialization function must be named
-:cfunc:`initname`, where *name* is the name of the module, and should be the
+:cfunc:`PyInit_name`, 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)
+ PyInit_spam(void)
{
- (void) Py_InitModule("spam", SpamMethods);
+ return PyModule_Create(&spammodule);
}
Note that PyMODINIT_FUNC declares the function as ``void`` return type,
@@ -319,33 +331,37 @@ declares any special linkage declarations required by the platform, and for C++
declares the function as ``extern "C"``.
When the Python program imports module :mod:`spam` for the first time,
-:cfunc:`initspam` is called. (See below for comments about embedding Python.)
-It calls :cfunc:`Py_InitModule`, which creates a "module object" (which is
-inserted in the dictionary ``sys.modules`` under the key ``"spam"``), and
+:cfunc:`PyInit_spam` is called. (See below for comments about embedding Python.)
+It calls :cfunc:`PyModule_Create`, which returns a module object, and
inserts built-in function objects into the newly created module based upon the
-table (an array of :ctype:`PyMethodDef` structures) that was passed as its
-second argument. :cfunc:`Py_InitModule` returns a pointer to the module object
-that it creates (which is unused here). It may abort with a fatal error for
+table (an array of :ctype:`PyMethodDef` structures) found in the module definition.
+:cfunc:`PyModule_Create` returns a pointer to the module object
+that it creates. It may abort with a fatal error for
certain errors, or return *NULL* if the module could not be initialized
-satisfactorily.
+satisfactorily. The init function must return the module object to its caller,
+so that it then gets inserted into ``sys.modules``.
-When embedding Python, the :cfunc:`initspam` function is not called
+When embedding Python, the :cfunc:`PyInit_spam` function is not called
automatically unless there's an entry in the :cdata:`_PyImport_Inittab` table.
-The easiest way to handle this is to statically initialize your
-statically-linked modules by directly calling :cfunc:`initspam` after the call
-to :cfunc:`Py_Initialize`::
+To add the module to the initialization table, use :cfunc:`PyImport_AppendInittab`,
+optionally followed by an import of the module::
int
main(int argc, char *argv[])
{
+ /* Add a builtin module, before Py_Initialize */
+ PyImport_AppendInittab("spam", PyInit_spam);
+
/* Pass argv[0] to the Python interpreter */
Py_SetProgramName(argv[0]);
/* Initialize the Python interpreter. Required. */
Py_Initialize();
- /* Add a static module */
- initspam();
+ /* Optionally import the module; alternatively,
+ import can be deferred until the embedded script
+ imports it. */
+ PyImport_ImportModule("spam");
An example may be found in the file :file:`Demo/embed/demo.c` in the Python
source distribution.
@@ -1154,15 +1170,15 @@ exporting module, not a client module. Finally, the module's initialization
function must take care of initializing the C API pointer array::
PyMODINIT_FUNC
- initspam(void)
+ PyInit_spam(void)
{
PyObject *m;
static void *PySpam_API[PySpam_API_pointers];
PyObject *c_api_object;
- m = Py_InitModule("spam", SpamMethods);
+ m = PyModule_Create(&spammodule);
if (m == NULL)
- return;
+ return NULL;
/* Initialize the C API pointer array */
PySpam_API[PySpam_System_NUM] = (void *)PySpam_System;
@@ -1172,10 +1188,11 @@ function must take care of initializing the C API pointer array::
if (c_api_object != NULL)
PyModule_AddObject(m, "_C_API", c_api_object);
+ return m;
}
Note that ``PySpam_API`` is declared ``static``; otherwise the pointer
-array would disappear when :func:`initspam` terminates!
+array would disappear when :func:`PyInit_spam` terminates!
The bulk of the work is in the header file :file:`spammodule.h`, which looks
like this::