-
-
Notifications
You must be signed in to change notification settings - Fork 32.2k
bpo-26515: Update C API docs to use PyModuleDef_Init() #8682
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -204,24 +204,34 @@ usually declare a static object variable at the beginning of your file:: | |
|
||
static PyObject *SpamError; | ||
|
||
and initialize it in your module's initialization function (:c:func:`PyInit_spam`) | ||
with an exception object (leaving out the error checking for now):: | ||
and initialize it in a function (:c:func:`spam_exec`) called from a module | ||
execution slot:: | ||
|
||
PyMODINIT_FUNC | ||
PyInit_spam(void) | ||
static int | ||
spam_exec(PyObject *module) | ||
{ | ||
PyObject *m; | ||
|
||
m = PyModule_Create(&spammodule); | ||
if (m == NULL) | ||
return NULL; | ||
|
||
SpamError = PyErr_NewException("spam.error", NULL, NULL); | ||
if (SpamError == NULL) { | ||
SpamError = PyErr_NewException("spam.error", NULL, NULL); | ||
if (SpamError == NULL) { | ||
goto fail; | ||
} | ||
} | ||
Py_INCREF(SpamError); | ||
PyModule_AddObject(m, "error", SpamError); | ||
return m; | ||
PyModule_AddObject(module, "error", SpamError); | ||
return 0; | ||
fail: | ||
Py_XDECREF(module); | ||
return -1; | ||
} | ||
|
||
then we need to specify the :c:func:`spam_exec` function for the | ||
c:var:`Py_mod_exec` slot:: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Missing the leading |
||
|
||
static struct PyModuleDef_Slot spam_slots[] = { | ||
{Py_mod_exec, spam_exec}, | ||
{0, NULL}, /* Sentinel */ | ||
}; | ||
|
||
Note that the Python name for the exception object is :exc:`spam.error`. The | ||
:c:func:`PyErr_NewException` function may create a class with the base class | ||
being :exc:`Exception` (unless another class is passed in instead of *NULL*), | ||
|
@@ -234,8 +244,8 @@ needed to ensure that it will not be discarded, causing :c:data:`SpamError` to | |
become a dangling pointer. Should it become a dangling pointer, C code which | ||
raises the exception could cause a core dump or other unintended side effects. | ||
|
||
We discuss the use of ``PyMODINIT_FUNC`` as a function return type later in this | ||
sample. | ||
We discuss the use of :c:macro:`PyMODINIT_FUNC` as a function return type later | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. With the modified example, this macro hasn't actually been referenced yet. Instead, the forward reference needs to explain that this list of slots will then be added to a |
||
in this sample. | ||
|
||
The :exc:`spam.error` exception can be raised in your extension module using a | ||
call to :c:func:`PyErr_SetString` as shown below:: | ||
|
@@ -291,15 +301,9 @@ on the heap in Python!) | |
|
||
If you have a C function that returns no useful argument (a function returning | ||
:c:type:`void`), the corresponding Python function must return ``None``. You | ||
need this idiom to do so (which is implemented by the :c:macro:`Py_RETURN_NONE` | ||
macro):: | ||
|
||
Py_INCREF(Py_None); | ||
return Py_None; | ||
can use the :c:macro:`Py_RETURN_NONE` macro to do so:: | ||
|
||
:c:data:`Py_None` is the C name for the special Python object ``None``. It is a | ||
genuine Python object rather than a *NULL* pointer, which means "error" in most | ||
contexts, as we have seen. | ||
Py_RETURN_NONE; | ||
|
||
|
||
.. _methodtable: | ||
|
@@ -310,24 +314,21 @@ The Module's Method Table and Initialization Function | |
I promised to show how :c:func:`spam_system` is called from Python programs. | ||
First, we need to list its name and address in a "method table":: | ||
|
||
static PyMethodDef SpamMethods[] = { | ||
... | ||
static PyMethodDef spam_methods[] = { | ||
{"system", spam_system, METH_VARARGS, | ||
"Execute a shell command."}, | ||
... | ||
{NULL, NULL, 0, NULL} /* Sentinel */ | ||
PyDoc_STR("Execute a shell command.")}, | ||
{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 :c:func:`PyArg_ParseTuple` is used. | ||
be ``METH_VARARGS`` or ``METH_VARARGS | METH_KEYWORDS``. | ||
|
||
When using only ``METH_VARARGS``, the function should expect the Python-level | ||
When using only :data:`METH_VARARGS`, the function should expect the Python-level | ||
parameters to be passed in as a tuple acceptable for parsing via | ||
:c:func 8000 :`PyArg_ParseTuple`; more information on this function is provided below. | ||
|
||
The :const:`METH_KEYWORDS` bit may be set in the third field if keyword | ||
The :data:`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 :c:func:`PyArg_ParseTupleAndKeywords` to parse the arguments to such a | ||
|
@@ -337,11 +338,15 @@ The method table must be referenced in the module definition structure:: | |
|
||
static 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 | ||
"spam", /* m_name - name of module */ | ||
spam_doc, /* m_doc - module documentation, may be NULL */ | ||
0, /* m_size - non-negative m_size is required for | ||
multi-phase initialization */ | ||
spam_methods, /* m_methods */ | ||
spam_slots, /* m_slots - required for multi-phase initialization */ | ||
NULL, /* m_traverse */ | ||
NULL, /* m_clear */ | ||
NULL /* m_free */ | ||
}; | ||
|
||
This structure, in turn, must be passed to the interpreter in the module's | ||
|
@@ -352,23 +357,16 @@ only non-\ ``static`` item defined in the module file:: | |
PyMODINIT_FUNC | ||
PyInit_spam(void) | ||
{ | ||
return PyModule_Create(&spammodule); | ||
return PyModuleDef_Init(&spammodule); | ||
} | ||
|
||
Note that PyMODINIT_FUNC declares the function as ``PyObject *`` 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 :mod:`spam` for the first time, | ||
:c:func:`PyInit_spam` is called. (See below for comments about embedding Python.) | ||
It calls :c:func:`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 :c:type:`PyMethodDef` structures) found in the module definition. | ||
:c:func:`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. The init function must return the module object to its caller, | ||
so that it then gets inserted into ``sys.modules``. | ||
Note that :c:macro:`PyMODINIT_FUNC` declares the function as ``PyObject *`` | ||
return type, declares any special linkage declarations required by the platform, | ||
and for C++ declares the function as ``extern "C"``. | ||
|
||
The initialization function :c:func:`PyInit_spam` returns a :c:type:`PyModuleDef` | ||
instance cast to ``PyObject*`` by calling :c:func:`PyModuleDef_Init`. See | ||
:ref:`multi-phase-initialization` for more information about this process. | ||
|
||
When embedding Python, the :c:func:`PyInit_spam` function is not called | ||
automatically unless there's an entry in the :c:data:`PyImport_Inittab` table. | ||
|
@@ -413,16 +411,9 @@ optionally followed by an import of the module:: | |
structures. | ||
|
||
A more substantial example module is included in the Python source distribution | ||
as :file:`Modules/xxmodule.c`. This file may be used as a template or simply | ||
as :source:`Modules/xxmodule.c`. This file may be used as a template or simply | ||
read as an example. | ||
|
||
.. note:: | ||
|
||
Unlike our ``spam`` example, ``xxmodule`` uses *multi-phase initialization* | ||
(new in Python 3.5), where a PyModuleDef structure is returned from | ||
``PyInit_spam``, and creation of the module is left to the import machinery. | ||
For details on multi-phase initialization, see :PEP:`489`. | ||
|
||
|
||
.. _compilation: | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a problem if the module is loaded more than once (for example, in multiple subinterpreters).
In that case,
spam_exec
would be executed multiple times, each time callingPyErr_NewException
and settingSpamError
to the newly created error object.This pointer needs to be part of per-module state.