blob: ddde6a3cfe474ce10938be280d35ee07354ec67b [file] [edit]
Python stable ABI (abi3, abi3t)
###############################
CPython's `stable ABI <https://docs.python.org/3/c-api/stable.html>`_ lets
one extension module run on every CPython release from the version it was
built for. pybind11 supports it from CPython 3.12 on: define
``Py_LIMITED_API`` to ``0x030C0000`` (or a newer version) and ship one
``*.abi3.so`` / ``*.pyd`` per platform instead of one module per Python
version.
CPython 3.15 adds a second stable ABI, ``abi3t`` (:pep:`803`). An ``abi3t``
module loads on every free-threaded *and* GIL-enabled CPython from 3.15 on, so
one ``*.abi3t.so`` per platform covers both builds. pybind11 supports it too:
define ``Py_TARGET_ABI3T`` to ``0x030F0000`` (or a newer version). Headers of
either build work. With free-threaded headers, ``Py_LIMITED_API`` alone also
selects ``abi3t``, because free-threaded CPython has no ``abi3``. See `abi3t`_
below for what differs.
Enabling it
===========
With CMake, add ``STABLE_ABI`` to ``pybind11_add_module`` (CMake 3.26+ and
the FindPython mode are required), or set ``PYBIND11_STABLE_ABI`` to make it
the default for a build tree:
.. code-block:: cmake
pybind11_add_module(example STABLE_ABI example.cpp)
``PYBIND11_STABLE_ABI_VERSION`` (default ``3.12``, raised to ``3.15`` for
``abi3t``) selects the targeted version. On free-threaded Python the modules
are always ``abi3t``. Set ``PYBIND11_ABI3T`` to ``ON`` to also build ``abi3t``
modules with GIL-enabled Python (plain CMake only; wheel builders tag the
wheel from the build Python, see `Building wheels`_):
.. code-block:: bash
cmake -S . -B build -DPYBIND11_STABLE_ABI=ON -DPYBIND11_ABI3T=ON
If your project calls ``find_package(Python)`` itself, add the
``Development.SABIModule`` component; pybind11 adds it only when it finds
Python itself.
``PRECOMPILE`` can be combined with ``STABLE_ABI``; the precompiled library
is then compiled against the limited API too, and one build tree cannot mix
stable-ABI and regular precompiled modules.
With scikit-build-core, set ``wheel.py-api = "cp312"`` in ``pyproject.toml``
(``"cp312.cp315t"`` to also get ``abi3t`` wheels from free-threaded Python;
the pybind11 defaults produce the matching module in both cases). This only
selects the wheel tag, and scikit-build-core ignores it when the build Python
is too old or is not CPython, so enable ``STABLE_ABI`` from the variables it
sets, before ``find_package(pybind11)`` (scikit-build-core 0.11+ sets
``SKBUILD_SABI_VERSION``; with older versions it is empty and pybind11 uses its
default):
.. code-block:: cmake
if(SKBUILD_SABI_COMPONENT)
set(PYBIND11_STABLE_ABI ON)
set(PYBIND11_STABLE_ABI_VERSION "${SKBUILD_SABI_VERSION}" CACHE STRING "")
endif()
If your project calls ``find_package(Python)`` itself, add the component that
scikit-build-core selects:
.. code-block:: cmake
find_package(Python REQUIRED COMPONENTS Interpreter Development.Module
${SKBUILD_SABI_COMPONENT})
With setuptools, pass ``py_limited_api=True`` (or a version such as
``"3.13"``) to ``Pybind11Extension``; the module is named ``*.abi3.so``
and ``Py_LIMITED_API`` is defined for you. Add a ``t`` (``"3.15t"``) for
``abi3t``, which is always used on free-threaded Python; ``Py_TARGET_ABI3T``
is then defined and the module is named ``*.abi3t*.so``. With GIL-enabled
Python, use ``build_ext`` from ``pybind11.setup_helpers`` to get that name.
Set the wheel tag with ``options={"bdist_wheel": {"py_limited_api": "cp312"}}``
in ``setup()``; ``bdist_wheel`` rejects ``"cp315t"``, so pass ``"cp315"`` and
build on free-threaded Python to get the ``abi3.abi3t`` tag.
With meson-python, set ``limited-api = true`` in ``[tool.meson-python]`` and
pass ``limited_api: '3.12'`` to ``py.extension_module()``. Meson defines
``Py_LIMITED_API`` from that value, so use ``'3.15'`` when the build Python is
free-threaded:
.. code-block:: meson
limited_api = py.get_variable('Py_GIL_DISABLED', 0).to_string() == '1' ? '3.15' : '3.12'
With any other build system, define ``Py_LIMITED_API=0x030C0000`` for every
translation unit, link no version-specific Python library (``python3.lib`` on
Windows), and name the module ``<name>.abi3.so`` (``<name>.pyd`` on Windows).
For ``abi3t``, define ``Py_TARGET_ABI3T=0x030F0000`` instead, link
``python3t.lib`` on Windows, and name the module ``<name>.abi3t.so``.
On CPython 3.15+, build tools can also use the platform-tagged suffixes
``.abi3-<platform>.so`` and ``.abi3t-<platform>.so`` (such as
``.abi3t-darwin.so``). CPython 3.15+ loads both forms, but CPython 3.12 to
3.14 only load ``.abi3.so``.
Building wheels
---------------
* Build ``abi3`` wheels with the CPython version you target. On 3.15+,
setuptools and CMake name the module ``.abi3-<platform>.so``, so a module
that targets 3.12 to 3.14 but is built with 3.15+ has a suffix that its
target versions do not load.
* Build ``abi3t`` wheels with free-threaded CPython 3.15+. With GIL-enabled
Python, scikit-build-core and setuptools tag the wheel ``abi3`` even when
the module is ``abi3t``, so the wheel installs where it cannot load.
* When a ``setup.py`` runs CMake, pass ``-DPython_EXECUTABLE=<sys.executable>``.
FindPython skips free-threaded interpreters by default, so it can find a
GIL-enabled Python and build an ``abi3`` module into an ``abi3t`` wheel.
* Every extension module in an ``abi3`` or ``abi3t`` wheel must use the
stable ABI; one version-specific module makes the wheel tag wrong.
pybind11 rejects the combination with PyPy, GraalPy, and free-threaded
CPython before 3.15 at compile time: they have no stable ABI.
What changes under the stable ABI
=================================
The C++ API of pybind11 is the same; the differences are in what is
available and in how a few things are implemented.
.. list-table::
:header-rows: 1
:widths: 30 20 50
* - Feature
- Stable ABI
- Notes
* - Classes, functions, casters, STL, numpy, Eigen
- supported
- Under abi3t, ``numpy.h`` needs NumPy 2.5+ at run time (it reads
array fields through NumPy's abi3t accessors). Older NumPy versions
install on 3.15, so require ``numpy>=2.5`` for abi3t wheels.
* - ``py::dynamic_attr()``
- supported
- Every instance reserves a ``__dict__`` slot (one pointer) that
``py::dynamic_attr()`` types use; there is no
``Py_TPFLAGS_MANAGED_DICT`` in the stable ABI.
* - Buffer protocol
- supported
- Through the ``Py_bf_*`` type slots.
* - ``py::gil_scoped_acquire`` / ``release``
- supported
- ``PYBIND11_SIMPLE_GIL_MANAGEMENT`` is forced; ``disarm()`` and
thread-state disassociation are not available.
* - ``py::metaclass(handle)``
- restricted
- The metaclass must not define ``__new__``, and a metaclass less
derived than ``pybind11_type`` resolves to ``pybind11_type``. The
metaclass of every base must be ``pybind11_type`` or a base of the
requested metaclass (``PyType_FromMetaclass()`` rejects a conflict).
* - ``py::custom_type_setup``
- not available
- Its callback receives a ``PyHeapTypeObject *``, which is opaque.
* - ``pybind11/embed.h``
- not available
- Embedding uses non-limited initialization functions.
* - ``pybind11/subinterpreter.h``
- not available
- Reads thread- and interpreter-state fields.
* - ``pybind11/chrono.h``
- supported
- The ``datetime`` C API is not in the stable ABI; fields are read as
attributes and objects are built by calling the ``datetime`` types.
* - GIL-held assertions (``PYBIND11_ASSERT_GIL_HELD_INCREF_DECREF``)
- not available
- ``PyGILState_Check()`` is not part of the stable ABI.
abi3t
=====
Under abi3t, ``PyObject`` and ``PyModuleDef`` are incomplete types and
``PyMutex`` and ``PyUnstable_TryIncRef()`` are not available. pybind11 then:
* stores its per-instance data as :pep:`697` type data
(``PyObject_GetTypeData()``) instead of embedding ``PyObject_HEAD``;
* exports the module through the :pep:`793` ``PyModExport_<name>`` hook
instead of ``PyInit_<name>``, so ``PYBIND11_MODULE`` is unchanged but
``py::module_::create_extension_module()``, the ``py::module_(name, doc)``
constructor, and the deprecated ``PYBIND11_PLUGIN`` are not available. If
you restrict exported symbols (a linker version script,
``-exported_symbols_list``, or a ``.def`` file), export ``PyModExport_*``
too;
* locks its internals with critical sections on a private object, and keeps
one weak reference per registered instance so that the instance registry
can hand out strong references safely (``PyWeakref_GetRef()``). This weak
reference is visible from Python: ``weakref.getweakrefcount()`` counts it,
and ``weakref.ref(obj)`` without a callback returns that same object.
``pybind11/numpy.h`` reads NumPy's object fields through the accessors NumPy
2.5 added for abi3t, so older NumPy versions are rejected at run time. The
internals tag is ``_abi3t``: an abi3t module and an abi3 module loaded
into the same GIL-enabled interpreter do not share internals (see below).
CPython's headers define ``Py_GIL_DISABLED`` for every abi3t build, so the
macro only says that the code must be thread-safe. To know whether the running
interpreter is free-threaded, check at run time, for example with
``sys._is_gil_enabled()`` or ``sysconfig.get_config_var("Py_GIL_DISABLED")``.
ABI isolation
=============
A stable-ABI module and a regular module can be loaded in one process, but
they do not share pybind11's internal state: the internals ID carries an
``_abi3`` or ``_abi3t`` tag identifying the compiled Python ABI target
(:pep:`803`), so each kind of module registers its own types and instances.
Types bound in one kind of module are opaque to the other, except
through the ``pybind11_conduit_v1`` protocol
(``include/pybind11/conduit/README.txt``), which bridges the two: the C++ ABI
is unchanged, so ``PYBIND11_PLATFORM_ABI_ID`` is the same.
Implementation notes and performance
====================================
Without access to CPython's struct layouts, pybind11 uses public functions
where it used to read fields directly. The costs are small and are confined
to specific operations:
* Type objects are created with ``PyType_FromMetaclass()`` and
``PyType_Spec``. This is also the default for regular builds on CPython
3.12+; define ``PYBIND11_TYPE_CREATION_VIA_SPEC=0`` (CMake:
``-DPYBIND11_TYPE_CREATION_VIA_SPEC=OFF``) to use the previous path, which
fills in the ``PyHeapTypeObject`` fields directly. Defining
``PYBIND11_BACKWARD_COMPATIBILITY_TP_DICTOFFSET`` in a regular build also
selects the previous path, so all bound classes share one dictionary layout.
* Instance allocation and deallocation look up ``tp_alloc``/``tp_free`` with
``PyType_GetSlot()``; the ``__dict__`` of ``py::dynamic_attr()`` instances
is a fixed slot in the instance layout.
* Attribute *assignment* on bound classes (``Type.static_prop = value``) walks
``__mro__`` and the class dictionaries instead of using ``_PyType_Lookup()``;
attribute reads use the metaclass default and are not affected.
* Methods are bound through a pybind11-provided ``instancemethod`` type and
``types.MethodType`` instead of ``PyInstanceMethod_Type`` /
``PyMethod_New()``.
* Tuple and list element access uses the checked function forms; type names
in error messages are reconstructed from ``__module__`` and ``__name__``.
* ``py::eval``/``py::exec`` compile with ``Py_CompileString()`` and run with
``PyEval_EvalCode()``; ``py::eval_file`` reads the file through Python.
Modules built for the stable ABI check the interpreter version at import:
any CPython from the targeted version on is accepted.