Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Fixup
  • Loading branch information
encukou committed Apr 2, 2026
commit f83f6b4458d8a90631a5aea36953c47b2c9a17fd
140 changes: 73 additions & 67 deletions Doc/c-api/stable.rst
Original file line number Diff line number Diff line change
Expand Up @@ -62,18 +62,13 @@

.. note::

For simplicity, this document talks about *extensions*, but the Stable ABI
For simplicity, this document talks about *extensions*, but Stable ABI
works the same way for all uses of the API – for example, embedding Python.

A Stable ABI is *versioned* using the first two numbers of the Python version.
For example, Stable ABI 3.14 corresponds to Python 3.14.
An extension compiled for Stable ABI 3.x is ABI-compatible with Python 3.x
and above.

There are two Stable ABIs:

- ``abi3``, introduced in Pyton 3.2, is compatible with
Comment thread
encukou marked this conversation as resolved.
Outdated
non-:term:`free threaded <free-threaded build>` builds of CPython.
**non**-:term:`free threaded <free-threaded build>` builds of CPython.
Comment thread
encukou marked this conversation as resolved.
Outdated

- ``abi3t``, introduced in Pyton 3.15, is compatible with
Comment thread
encukou marked this conversation as resolved.
Outdated
:term:`free threaded <free-threaded build>` builds of CPython.
Expand All @@ -84,50 +79,47 @@
``abi3t`` was added in :pep:`803`

It is possible for an extension to be compiled for *both* ``abi3`` and
``abi3t`` at the same time.
``abi3t`` at the same time; the result will be compatible with
both free-threaded and non-free-threaded builds of Python.
Currently, this has no downsides compared to compiling for ``abi3t`` only.

The Stable ABIs come with several caveats:

- Extensions that target a stable ABI must only use a limited subset of
the C API. This subset is known as the :dfn:`Limited API`; its contents
are :ref:`listed below <limited-api-list>`.

- Compiling for a Stable ABI will disable some optimizations.
In particular, common functions cannot be inlined to take advantage of the
internal implementation details.
Each Stable ABI is versioned using the first two numbers of the Python version.
For example, Stable ABI 3.14 corresponds to Python 3.14.
An extension compiled for Stable ABI 3.x is ABI-compatible with Python 3.x
and above.

- Stable ABI prevents *ABI* issues, like linker errors due to missing
symbols or data corruption due to changes in structure layouts or function
signatures.
However, other changes in Python can change the *behavior* of extensions.
See Python's Backwards Compatibility Policy (:pep:`387`) for details.
Extensions that target a stable ABI must only use a limited subset of
the C API. This subset is known as the :dfn:`Limited API`; its contents
are :ref:`listed below <limited-api-list>`.

On Windows, extensions that use a Stable ABI should be linked against
``python3.dll`` rather than a version-specific library such as
``python39.dll``.
This library only exposes the relevant symbols.

On some platforms, Python will look for and load shared library files named
with the ``abi3`` or ``abi3t`` tag (e.g. ``mymodule.abi3.so``).
with the ``abi3`` or ``abi3t`` tag (for example, ``mymodule.abi3.so``).
:term:`Free threaded <free-threaded build>` interpreters only recognize the
``abi3t`` tag, while non-free threaded ones will prefer ``abi3`` but fall back
Comment thread
hugovk marked this conversation as resolved.
Outdated
to ``abi3t``.
Thus, extensions compatible with both flavors should use the ``abi3t`` tag.
Thus, extensions compatible with both ABIs should use the ``abi3t`` tag.

Python does not check if such extensions conform to a Stable ABI.
Extension authors are encouraged to check using the :c:macro:`Py_mod_abi`
slot or the :c:func:`PyABIInfo_Check` function, but, the user
Python does not necessarily check that extensions it loads
have compatible ABI.
Extension authors are encouraged to add a check using the :c:macro:`Py_mod_abi`
slot or the :c:func:`PyABIInfo_Check` function, but the user
(or their packaging tool) is ultimately responsible for ensuring that,
for example, extensions built for Stable ABI 3.10 are not installed for lower
versions of Python.

All functions in the Stable ABI are present as functions in Python's shared
All functions in Stable ABI are present as functions in Python's shared
library, not solely as macros.
They are usable from languages that don't use the C preprocessor,
such as Python via :py:mod:`ctypes`.
This makes them usable are usable from languages that don't use the C
preprocessor, including Python's :py:mod:`ctypes`.


.. _abi3-compiling:

Compiling for Stable ABI
------------------------

Expand All @@ -138,22 +130,23 @@
extension filenames and other metadata.
Prefer using the tool's options over defining the macros manually.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe setuptools is a poor example to use above then? Because setuptools expects users to set the build flags manually...

You could delete the "(For example, SetupTools)" above, or maybe refer to meson-python or scikit-build-core instead? These days that's what I recommend to people depending on if they already use CMake or not.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AFAIK Setuptools is the most widely known build tool; the example is there to clarify what kind of β€œbuild tool” I'm talking about.

Setuptools has a --py_limited_api argument. All tools will ideally need an update for abi3t.


The rest of this section is relevant for tool authors, and for people who
compile extensions manually.
The rest of this section is mainly relevant for tool authors, and for
people who compile extensions manually.

.. seealso:: `list of recommended tools`_ in the Python Packaging User Guide

.. _list of recommended tools: https://packaging.python.org/en/latest/guides/tool-recommendations/#build-backends-for-extension-modules

To compile for a Stable ABI, define one or both of the following macros
before including ``Python.h`` to the lowest Python version your extension
should support, in :c:macro:`Py_PACK_VERSION` format.
to the lowest Python version your extension should support, in
:c:macro:`Py_PACK_VERSION` format.
Typically, you should choose a specific value rather than the version of
the Python headers you are compiling against.

Since the :c:macro:`Py_PACK_VERSION` is not available before including
``Python.h``, you will need to use the number directly.
For reference, the values for a few Python versions are:
The macro(s) must be defined before including ``Python.h``.
Comment thread
encukou marked this conversation as resolved.
Outdated
Since :c:macro:`Py_PACK_VERSION` is not available at this point, you
will need to use the numeric value directly.
For reference, the values for a few recent Python versions are:

.. version-hex-cheatsheet::

Expand All @@ -166,18 +159,20 @@

Target ``abi3``, that is,
non-:term:`free threaded <free-threaded build>` builds of CPython.
See :ref:`above <abi3-compiling>` for common information.

.. c:macro:: Py_TARGET_ABI3T

Target ``abi3t``, that is,
:term:`free threaded <free-threaded build>` builds of CPython.
See :ref:`above <abi3-compiling>` for common information.
Comment thread
encukou marked this conversation as resolved.

.. versionadded:: next

Despite the different naming, the macros are similar;
the name :c:macro:`!Py_LIMITED_API` is kept for backwards compatibility.
Both macros specify a target ABI; the different naming style is due to
backwards compatibility.

.. admonition:: Historical note

Check warning on line 175 in Doc/c-api/stable.rst

View workflow job for this annotation

GitHub Actions / Docs / Docs

c:func reference target not found: PyErr_Display [ref.func]

You can also define ``Py_LIMITED_API`` as ``3``. This works the same as
``0x03020000`` (Python 3.2, the version that introduced Stable ABI).
Expand Down Expand Up @@ -212,30 +207,33 @@
Compiling for Stable ABI disables this inlining, allowing stability as
Python's data structures are improved, but possibly reducing performance.

By leaving out the :c:macro:`!Py_LIMITED_API`` or :c:macro:`!Py_TARGET_ABI3T`
By leaving out the :c:macro:`!Py_LIMITED_API` or :c:macro:`!Py_TARGET_ABI3T`
definition, it is possible to compile Stable-ABI-compatible source
for a version-specific ABI, possibly improving performance for a specific
Python version.


Limited API Caveats
-------------------

Note that compiling with :c:macro:`Py_LIMITED_API` or :c:macro:`Py_TARGET_ABI3T`
is *not* a complete guarantee that code will be compatible with the
expected Python versions.
The macros only cover definitions, not other issues such as expected semantics.

One issue that the macros do not guard against is calling a function
with arguments that are invalid in a lower Python version.
for a version-specific ABI.
A potentially faster version-specific extension can then be distributed
alongside a version compiled for Stable ABI -- a slower but more compatible
fallback.


Stable ABI Caveats
------------------

Note that compiling for Stable ABI is *not* a complete guarantee that code will
be compatible with the expected Python versions.
Stable ABI prevents *ABI* issues, like linker errors due to missing
Comment on lines +231 to +233
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we need to precede "Stable ABI" with "the"?

Suggested change
Note that compiling for Stable ABI is *not* a complete guarantee that code will
be compatible with the expected Python versions.
Stable ABI prevents *ABI* issues, like linker errors due to missing
Note that compiling for the Stable ABI is *not* a complete guarantee that code will
be compatible with the expected Python versions.
The Stable ABI prevents *ABI* issues, like linker errors due to missing

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Even if there's two of them?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, not too sure about the rules here. What about "the Stable ABIs"?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The way I wrote it still sounds best to me...

symbols or data corruption due to changes in structure layouts or function
signatures.
However, other changes in Python can change the *behavior* of extensions.
See Python's Backwards Compatibility Policy (:pep:`387`) for details.
Comment thread
encukou marked this conversation as resolved.
Outdated

One issue that the :c:macro:`Py_TARGET_ABI3T` and :c:macro:`Py_LIMITED_API`
macros do not guard against is calling a function with arguments that are
invalid in a lower Python version.
For example, consider a function that starts accepting ``NULL`` for an
argument. In Python 3.9, ``NULL`` now selects a default behavior, but in
Python 3.8, the argument will be used directly, causing a ``NULL`` dereference
and crash. A similar argument works for fields of structs.

Another issue is that some struct fields are currently not hidden when
the macros are defined, even though they're part of the Limited API.

For these reasons, we recommend testing an extension with *all* minor Python
versions it supports.

Expand All @@ -245,11 +243,11 @@
even unintentionally, as bugs).

Also note that while compiling with ``Py_LIMITED_API`` 3.8 means that the
extension will *load* on Python 3.12, and *compile* with Python 3.12,
extension should *load* on Python 3.12, and *compile* with Python 3.12,
the same source will not necessarily compile with ``Py_LIMITED_API``
set to 3.12.
In general: parts of the Limited API may be deprecated and removed,
provided that the Stable ABI stays stable.
In general, parts of the Limited API may be deprecated and removed,
provided that Stable ABI stays stable.


.. _stable-abi-platform:
Expand Down Expand Up @@ -372,7 +370,7 @@

.. c:macro:: PyABIInfo_STABLE

Specifies that the stable ABI is used.
Specifies that Stable ABI is used.

.. c:macro:: PyABIInfo_INTERNAL

Expand All @@ -383,15 +381,22 @@

.. c:macro:: PyABIInfo_FREETHREADED

Specifies ABI compatible with free-threading builds of CPython.
Specifies ABI compatible with :term:`free-threaded builds
<free-threaded build>` of CPython.
(That is, ones compiled with :option:`--disable-gil`; with ``t``
in :py:data:`sys.abiflags`)

.. c:macro:: PyABIInfo_GIL

Specifies ABI compatible with non-free-threading builds of CPython
Specifies ABI compatible with non-free-threaded builds of CPython
(ones compiled *without* :option:`--disable-gil`).

.. c:macro:: PyABIInfo_FREETHREADING_AGNOSTIC

Specifies ABI compatible with both free-threaded and
non-free-threaded builds of CPython, that is, both
``abi3`` and ``abi3t``.

.. c:member:: uint32_t build_version

The version of the Python headers used to build the code, in the format
Expand All @@ -405,10 +410,11 @@

The ABI version.

For the Stable ABI, this field should be the value of
:c:macro:`Py_LIMITED_API`
(except if :c:macro:`Py_LIMITED_API` is ``3``; use
:c:expr:`Py_PACK_VERSION(3, 2)` in that case).
For Stable ABI, this field should be the value of
:c:macro:`Py_LIMITED_API` or :c:macro:`Py_TARGET_ABI3T`.
If both are defined, use the smaller value.
(If :c:macro:`Py_LIMITED_API` is ``3``; use
:c:expr:`Py_PACK_VERSION(3, 2)` instead of ``3``.)

Otherwise, it should be set to :c:macro:`PY_VERSION_HEX`.

Expand Down
3 changes: 2 additions & 1 deletion Doc/tools/extensions/c_annotations.py
Original file line number Diff line number Diff line change
Expand Up @@ -377,7 +377,8 @@ class VersionHexCheatsheet(SphinxDirective):
"""Show results of Py_PACK_VERSION(3, x) for a few relevant Python versions

This is useful for defining version before Python.h is included.
It should auto-update to the version being documented, hence the extension.
It should auto-update with the version being documented, so it must be an
extension.
"""
has_content = False
required_arguments = 0
Expand Down
21 changes: 15 additions & 6 deletions Doc/whatsnew/3.15.rst
Original file line number Diff line number Diff line change
Expand Up @@ -387,15 +387,15 @@ agen() for x in a)``.
:pep:`903`: ``abi3t`` -- Stable ABI for Free-Threaded Builds
Comment thread
encukou marked this conversation as resolved.
Outdated
Comment thread
encukou marked this conversation as resolved.
Outdated
------------------------------------------------------------

C extensions that target the :ref:`Stable ABI <stable-abi>`
can now be compiled to be compatible with
both :term:`free-threaded build <free-threaded build>` builds of CPython
and "traditional" builds with the :term:`GIL` enabled.
This mode usually requires some non-trivial changes to the source code;
C extensions that target the :ref:`Stable ABI <stable-abi>` can now be
compiled for the new *Stable ABI for Free-Threaded Builds* (also known
as ``abi3t``), which makes them compatible with
:term:`free-threaded build <free-threaded build>` builds of CPython.
Comment thread
encukou marked this conversation as resolved.
Outdated
This usually requires some non-trivial changes to the source code;
specifically:

- Switching to API introduced in :pep:`697` (Python 3.12), such as
negative :c:member:`~PyType_Spec.basicsize` and
negative :c:member:`~PyType_Spec.basicsize`
:c:func:`PyObject_GetTypeData`, rather than making :c:type:`PyObject`
part of the instance struct; and
- Switching from a ``PyInit_`` function to a new export hook,
Expand All @@ -407,6 +407,15 @@ Extensions that cannot switch to ``abi3t`` should continue to build for
the existing Stable ABI (``abi3``) and the version-specific ABI for
free-threading (``cp315t``) separately.

Stable ABI for Free-Threaded Builds should typically
be selected in a build tool (such as Setuptools, ``meson-python``, Cython,
Scikit-build-core, Maturin, and similar).
Comment thread
encukou marked this conversation as resolved.
Outdated
Comment thread
encukou marked this conversation as resolved.
Outdated
At the time of writing this entry, these tools did **not** support ``abi3t``.
Comment thread
encukou marked this conversation as resolved.
Outdated
If this is the case for "your" tool, compile for ``cp315t`` separately.
Comment thread
encukou marked this conversation as resolved.
Outdated
If not using a build tool -- or when writing such a tool -- you can select
``abi3t`` by setting the macro :c:macro:`!Py_TARGET_ABI3T` as discussed
Comment thread
ZeroIntensity marked this conversation as resolved.
in :ref:`abi3-compiling`.


.. _whatsnew315-improved-error-messages:

Expand Down
2 changes: 0 additions & 2 deletions Tools/check-c-api-docs/ignored_c_api.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@ Py_HasFileSystemDefaultEncoding
Py_UTF8Mode
# pyhash.h
Py_HASH_EXTERNAL
# modsupport.h
PyABIInfo_FREETHREADING_AGNOSTIC
# object.h
Py_INVALID_SIZE
# pyexpat.h
Expand Down
Loading