aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/Doc/c-api
diff options
context:
space:
mode:
Diffstat (limited to 'Doc/c-api')
-rw-r--r--Doc/c-api/allocation.rst2
-rw-r--r--Doc/c-api/code.rst2
-rw-r--r--Doc/c-api/function.rst2
-rw-r--r--Doc/c-api/init_config.rst2
-rw-r--r--Doc/c-api/intro.rst42
-rw-r--r--Doc/c-api/lifecycle.rst6
-rw-r--r--Doc/c-api/module.rst42
-rw-r--r--Doc/c-api/stable.rst1
-rw-r--r--Doc/c-api/sys.rst51
-rw-r--r--Doc/c-api/typeobj.rst2
-rw-r--r--Doc/c-api/unicode.rst25
11 files changed, 143 insertions, 34 deletions
diff --git a/Doc/c-api/allocation.rst b/Doc/c-api/allocation.rst
index f8d01a3f29b..59d913a0462 100644
--- a/Doc/c-api/allocation.rst
+++ b/Doc/c-api/allocation.rst
@@ -153,6 +153,6 @@ Allocating Objects on the Heap
.. seealso::
- :c:func:`PyModule_Create`
+ :ref:`moduleobjects`
To allocate and create extension modules.
diff --git a/Doc/c-api/code.rst b/Doc/c-api/code.rst
index 6eae24b38fa..42594f063b0 100644
--- a/Doc/c-api/code.rst
+++ b/Doc/c-api/code.rst
@@ -182,7 +182,7 @@ bound into a function.
Type of a code object watcher callback function.
If *event* is ``PY_CODE_EVENT_CREATE``, then the callback is invoked
- after `co` has been fully initialized. Otherwise, the callback is invoked
+ after *co* has been fully initialized. Otherwise, the callback is invoked
before the destruction of *co* takes place, so the prior state of *co*
can be inspected.
diff --git a/Doc/c-api/function.rst b/Doc/c-api/function.rst
index 58792edeed2..63b78f67767 100644
--- a/Doc/c-api/function.rst
+++ b/Doc/c-api/function.rst
@@ -169,7 +169,7 @@ There are a few functions specific to Python functions.
unpredictable effects, including infinite recursion.
If *event* is ``PyFunction_EVENT_CREATE``, then the callback is invoked
- after `func` has been fully initialized. Otherwise, the callback is invoked
+ after *func* has been fully initialized. Otherwise, the callback is invoked
before the modification to *func* takes place, so the prior state of *func*
can be inspected. The runtime is permitted to optimize away the creation of
function objects when possible. In such cases no event will be emitted.
diff --git a/Doc/c-api/init_config.rst b/Doc/c-api/init_config.rst
index e1931655618..4fd10224262 100644
--- a/Doc/c-api/init_config.rst
+++ b/Doc/c-api/init_config.rst
@@ -2111,7 +2111,7 @@ initialization::
/* Specify sys.path explicitly */
/* If you want to modify the default set of paths, finish
- initialization first and then use PySys_GetObject("path") */
+ initialization first and then use PySys_GetAttrString("path") */
config.module_search_paths_set = 1;
status = PyWideStringList_Append(&config.module_search_paths,
L"/path/to/stdlib");
diff --git a/Doc/c-api/intro.rst b/Doc/c-api/intro.rst
index 0c20ad17194..41856922110 100644
--- a/Doc/c-api/intro.rst
+++ b/Doc/c-api/intro.rst
@@ -127,7 +127,7 @@ complete listing.
item defined in the module file. Example::
static struct PyModuleDef spam_module = {
- PyModuleDef_HEAD_INIT,
+ .m_base = PyModuleDef_HEAD_INIT,
.m_name = "spam",
...
};
@@ -135,7 +135,7 @@ complete listing.
PyMODINIT_FUNC
PyInit_spam(void)
{
- return PyModule_Create(&spam_module);
+ return PyModuleDef_Init(&spam_module);
}
@@ -838,3 +838,41 @@ after every statement run by the interpreter.)
Please refer to :file:`Misc/SpecialBuilds.txt` in the Python source distribution
for more detailed information.
+
+
+.. _c-api-tools:
+
+Recommended third party tools
+=============================
+
+The following third party tools offer both simpler and more sophisticated
+approaches to creating C, C++ and Rust extensions for Python:
+
+* `Cython <https://cython.org/>`_
+* `cffi <https://cffi.readthedocs.io>`_
+* `HPy <https://hpyproject.org/>`_
+* `nanobind <https://github.com/wjakob/nanobind>`_ (C++)
+* `Numba <https://numba.pydata.org/>`_
+* `pybind11 <https://pybind11.readthedocs.io/>`_ (C++)
+* `PyO3 <https://pyo3.rs/>`_ (Rust)
+* `SWIG <https://www.swig.org>`_
+
+Using tools such as these can help avoid writing code that is tightly bound to
+a particular version of CPython, avoid reference counting errors, and focus
+more on your own code than on using the CPython API. In general, new versions
+of Python can be supported by updating the tool, and your code will often use
+newer and more efficient APIs automatically. Some tools also support compiling
+for other implementations of Python from a single set of sources.
+
+These projects are not supported by the same people who maintain Python, and
+issues need to be raised with the projects directly. Remember to check that the
+project is still maintained and supported, as the list above may become
+outdated.
+
+.. seealso::
+
+ `Python Packaging User Guide: Binary Extensions <https://packaging.python.org/guides/packaging-binary-extensions/>`_
+ The Python Packaging User Guide not only covers several available
+ tools that simplify the creation of binary extensions, but also
+ discusses the various reasons why creating an extension module may be
+ desirable in the first place.
diff --git a/Doc/c-api/lifecycle.rst b/Doc/c-api/lifecycle.rst
index 0e2ffc096ca..5a170862a26 100644
--- a/Doc/c-api/lifecycle.rst
+++ b/Doc/c-api/lifecycle.rst
@@ -55,16 +55,14 @@ that must be true for *B* to occur after *A*.
.. image:: lifecycle.dot.svg
:align: center
:class: invert-in-dark-mode
- :alt: Diagram showing events in an object's life. Explained in detail
- below.
+ :alt: Diagram showing events in an object's life. Explained in detail below.
.. only:: latex
.. image:: lifecycle.dot.pdf
:align: center
:class: invert-in-dark-mode
- :alt: Diagram showing events in an object's life. Explained in detail
- below.
+ :alt: Diagram showing events in an object's life. Explained in detail below.
.. container::
:name: life-events-graph-description
diff --git a/Doc/c-api/module.rst b/Doc/c-api/module.rst
index f7f4d37d4c7..710135dca89 100644
--- a/Doc/c-api/module.rst
+++ b/Doc/c-api/module.rst
@@ -288,22 +288,40 @@ An alternate way to specify extensions is to request "multi-phase initialization
Extension modules created this way behave more like Python modules: the
initialization is split between the *creation phase*, when the module object
is created, and the *execution phase*, when it is populated.
-The distinction is similar to the :py:meth:`!__new__` and :py:meth:`!__init__` methods
-of classes.
+The distinction is similar to the :py:meth:`~object.__new__` and
+:py:meth:`~object.__init__` methods of classes.
Unlike modules created using single-phase initialization, these modules are not
-singletons: if the *sys.modules* entry is removed and the module is re-imported,
-a new module object is created, and the old module is subject to normal garbage
-collection -- as with Python modules.
-By default, multiple modules created from the same definition should be
-independent: changes to one should not affect the others.
-This means that all state should be specific to the module object (using e.g.
-using :c:func:`PyModule_GetState`), or its contents (such as the module's
-:attr:`~object.__dict__` or individual classes created with :c:func:`PyType_FromSpec`).
+singletons.
+For example, if the :py:attr:`sys.modules` entry is removed and the module
+is re-imported, a new module object is created, and typically populated with
+fresh method and type objects.
+The old module is subject to normal garbage collection.
+This mirrors the behavior of pure-Python modules.
+
+Additional module instances may be created in
+:ref:`sub-interpreters <sub-interpreter-support>`
+or after after Python runtime reinitialization
+(:c:func:`Py_Finalize` and :c:func:`Py_Initialize`).
+In these cases, sharing Python objects between module instances would likely
+cause crashes or undefined behavior.
+
+To avoid such issues, each instance of an extension module should
+be *isolated*: changes to one instance should not implicitly affect the others,
+and all state, including references to Python objects, should be specific to
+a particular module instance.
+See :ref:`isolating-extensions-howto` for more details and a practical guide.
+
+A simpler way to avoid these issues is
+:ref:`raising an error on repeated initialization <isolating-extensions-optout>`.
All modules created using multi-phase initialization are expected to support
-:ref:`sub-interpreters <sub-interpreter-support>`. Making sure multiple modules
-are independent is typically enough to achieve this.
+:ref:`sub-interpreters <sub-interpreter-support>`, or otherwise explicitly
+signal a lack of support.
+This is usually achieved by isolation or blocking repeated initialization,
+as above.
+A module may also be limited to the main interpreter using
+the :c:data:`Py_mod_multiple_interpreters` slot.
To request multi-phase initialization, the initialization function
(PyInit_modulename) returns a :c:type:`PyModuleDef` instance with non-empty
diff --git a/Doc/c-api/stable.rst b/Doc/c-api/stable.rst
index 124e58cf950..9b65e0b8d23 100644
--- a/Doc/c-api/stable.rst
+++ b/Doc/c-api/stable.rst
@@ -51,6 +51,7 @@ It is generally intended for specialized, low-level tools like debuggers.
Projects that use this API are expected to follow
CPython development and spend extra effort adjusting to changes.
+.. _stable-application-binary-interface:
Stable Application Binary Interface
===================================
diff --git a/Doc/c-api/sys.rst b/Doc/c-api/sys.rst
index b3c89800e38..b34936dd55e 100644
--- a/Doc/c-api/sys.rst
+++ b/Doc/c-api/sys.rst
@@ -258,10 +258,57 @@ These are utility functions that make functionality from the :mod:`sys` module
accessible to C code. They all work with the current interpreter thread's
:mod:`sys` module's dict, which is contained in the internal thread state structure.
+.. c:function:: PyObject *PySys_GetAttr(PyObject *name)
+
+ Get the attribute *name* of the :mod:`sys` module.
+ Return a :term:`strong reference`.
+ Raise :exc:`RuntimeError` and return ``NULL`` if it does not exist or
+ if the :mod:`sys` module cannot be found.
+
+ If the non-existing object should not be treated as a failure, you can use
+ :c:func:`PySys_GetOptionalAttr` instead.
+
+ .. versionadded:: next
+
+.. c:function:: PyObject *PySys_GetAttrString(const char *name)
+
+ This is the same as :c:func:`PySys_GetAttr`, but *name* is
+ specified as a :c:expr:`const char*` UTF-8 encoded bytes string,
+ rather than a :c:expr:`PyObject*`.
+
+ If the non-existing object should not be treated as a failure, you can use
+ :c:func:`PySys_GetOptionalAttrString` instead.
+
+ .. versionadded:: next
+
+.. c:function:: int PySys_GetOptionalAttr(PyObject *name, PyObject **result)
+
+ Variant of :c:func:`PySys_GetAttr` which doesn't raise
+ exception if the object does not exist.
+
+ * Set *\*result* to a new :term:`strong reference` to the object and
+ return ``1`` if the object exists.
+ * Set *\*result* to ``NULL`` and return ``0`` without setting an exception
+ if the object does not exist.
+ * Set an exception, set *\*result* to ``NULL``, and return ``-1``,
+ if an error occurred.
+
+ .. versionadded:: next
+
+.. c:function:: int PySys_GetOptionalAttrString(const char *name, PyObject **result)
+
+ This is the same as :c:func:`PySys_GetOptionalAttr`, but *name* is
+ specified as a :c:expr:`const char*` UTF-8 encoded bytes string,
+ rather than a :c:expr:`PyObject*`.
+
+ .. versionadded:: next
+
.. c:function:: PyObject *PySys_GetObject(const char *name)
- Return the object *name* from the :mod:`sys` module or ``NULL`` if it does
- not exist, without setting an exception.
+ Similar to :c:func:`PySys_GetAttrString`, but return a :term:`borrowed
+ reference` and return ``NULL`` *without* setting exception on failure.
+
+ Preserves exception that was set before the call.
.. c:function:: int PySys_SetObject(const char *name, PyObject *v)
diff --git a/Doc/c-api/typeobj.rst b/Doc/c-api/typeobj.rst
index 5df0c0fe608..91046c0e6f1 100644
--- a/Doc/c-api/typeobj.rst
+++ b/Doc/c-api/typeobj.rst
@@ -1238,7 +1238,7 @@ and :c:data:`PyType_Type` effectively act as defaults.)
.. c:macro:: Py_TPFLAGS_MANAGED_DICT
- This bit indicates that instances of the class have a `~object.__dict__`
+ This bit indicates that instances of the class have a :attr:`~object.__dict__`
attribute, and that the space for the dictionary is managed by the VM.
If this flag is set, :c:macro:`Py_TPFLAGS_HAVE_GC` should also be set.
diff --git a/Doc/c-api/unicode.rst b/Doc/c-api/unicode.rst
index cdd90d05b70..45f50ba5f97 100644
--- a/Doc/c-api/unicode.rst
+++ b/Doc/c-api/unicode.rst
@@ -1461,10 +1461,6 @@ the user settings on the machine running the codec.
.. versionadded:: 3.3
-Methods & Slots
-"""""""""""""""
-
-
.. _unicodemethodsandslots:
Methods and Slot Functions
@@ -1726,10 +1722,6 @@ They all return ``NULL`` or ``-1`` if an exception occurs.
from user input, prefer calling :c:func:`PyUnicode_FromString` and
:c:func:`PyUnicode_InternInPlace` directly.
- .. impl-detail::
-
- Strings interned this way are made :term:`immortal`.
-
.. c:function:: unsigned int PyUnicode_CHECK_INTERNED(PyObject *str)
@@ -1806,9 +1798,24 @@ object.
See also :c:func:`PyUnicodeWriter_DecodeUTF8Stateful`.
+.. c:function:: int PyUnicodeWriter_WriteASCII(PyUnicodeWriter *writer, const char *str, Py_ssize_t size)
+
+ Write the ASCII string *str* into *writer*.
+
+ *size* is the string length in bytes. If *size* is equal to ``-1``, call
+ ``strlen(str)`` to get the string length.
+
+ *str* must only contain ASCII characters. The behavior is undefined if
+ *str* contains non-ASCII characters.
+
+ On success, return ``0``.
+ On error, set an exception, leave the writer unchanged, and return ``-1``.
+
+ .. versionadded:: next
+
.. c:function:: int PyUnicodeWriter_WriteWideChar(PyUnicodeWriter *writer, const wchar_t *str, Py_ssize_t size)
- Writer the wide string *str* into *writer*.
+ Write the wide string *str* into *writer*.
*size* is a number of wide characters. If *size* is equal to ``-1``, call
``wcslen(str)`` to get the string length.