diff options
author | Martin v. Löwis <martin@v.loewis.de> | 2008-06-11 05:26:20 (GMT) |
---|---|---|
committer | Martin v. Löwis <martin@v.loewis.de> | 2008-06-11 05:26:20 (GMT) |
commit | 1a21451b1d73b65af949193208372e86bf308411 (patch) | |
tree | 8e98d7be9e249b011ae9380479656e5284ec0234 /Doc/extending | |
parent | cdf94635d7e364f9ce1905bafa5b540f4d16147c (diff) | |
download | cpython-1a21451b1d73b65af949193208372e86bf308411.zip cpython-1a21451b1d73b65af949193208372e86bf308411.tar.gz cpython-1a21451b1d73b65af949193208372e86bf308411.tar.bz2 |
Implement PEP 3121: new module initialization and finalization API.
Diffstat (limited to 'Doc/extending')
-rw-r--r-- | Doc/extending/extending.rst | 67 |
1 files changed, 42 insertions, 25 deletions
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:: |