pybind11 3.0.0

pybind11 logo

Pybind11 3.0 has been released! I would like to highlight some of the key changes below; be sure to check out the changelog and upgrade guide for more information! This release includes an ABI bump, the first required bump in many years on Unix (Windows has had required bumps more often). This release contains the multi-year smart-holder branch, multi-phase init and subinterpreter support, py::native_enum, an interface to warnings, typing improvements, and more. CMake now defaults to FindPython mode.

Support for Python 3.14, 3.14t, GraalPy, PyPy 3.11, and iOS have been added, while legacy support for Python 3.7, PyPy 3.8/3.9, and CMake <3.15 has been removed. Most deprecated features have been kept for this release, but anything producing a warning in 3.0 may be removed in a future 3.x version.

Smart Holder

After years, Google’s smart-holder branch is finally merged. This gives you the ability to opt-into a custom smart pointer (or use any other smart pointer, it’s now templated).

This:

py::class_<Pet>

is now shorthand for this:

py::class_<Pet, std::shared_ptr>

And you can instead do this:

py::class_<Pet, py::smart_holder>

(There’s also a py::classh shortcut, or you can easily make your own). This new holder is more powerful, allowing shared/unique pointer conversion, disowning a Python object, trampoline objects, const smart pointers, and std::enable_shared_from_this.

Native enums

You can now replace py::enum with py::native_enum, which will produce normal Python 3.4+ enum.Enum instances instead of the old custom class we had for enums (that pre-dated the modern enums, so doesn’t behave quite how people now expect).

#include <pybind11/pybind11.h>
#include <pybind11/native_enum.h>

using py = pybind11;

enum class altitude : char {
    high = 'h',
    low = 'l'
};

PYBIND11_MODULE(native_enum_demo, m) {
    py::native_enum<altitude>(m, "altitude")
             .value("high", altitude::high)
             .value("low", altitude::low)
             .finalize();
}

NumPy scalars

You can take and produce NumPy scalars. For example:

m.def("add", [](py::numpy_scalar<float> a, py::numpy_scalar<float> b) {
    return py::make_scalar(a + b);
});
m.def("add", [](py::numpy_scalar<double> a, py::numpy_scalar<double> b) {
    return py::make_scalar(a + b);
});

The supported types are bool_, int8, int16, int32, int64, uint8, uint16, uint32, uint64, float32, float64, complex64, and complex128.

Subintepreters

We now use multiphase init for initialization. We also provide new tags that allow you to opt into subinterpreter support; py::multiple_interpreters::per_interpreter_gil() for full support, or py::multiple_interpreters::shared_gil() for legacy subinterpeters with shared GIL.

This all works with embedded interpreters, as well, so PYBIND11_EMBEDED_MODULE supports these new tags, as well as py::mod_gil_not_used() (free-threading) too. pybind11/subinterpreter.h is new.

Slightly related, we also now have py::scoped_critical_section for free-threaded use.

Typing improvements

There are a lot of typing improvements, so using something like mypy’s stubgen should produce much better .pyi files.

New and removed platforms

We now support iOS. You can use cibuildwheel to create iOS wheels.

We now support GraalPy. You can use cibuildwheel, GitHub Actions, uv, or other methods to get GraalPy. We support PyPy 3.11 now too. We added support C++20 on Windows and C++23 on Linux.

We now support Python 3.14 betas. We also have significantly improved our support for free threaded Python with several bugfixes.

We no longer support CPython 3.7, PyPy 3.8 and 3.9, and CMake <3.15. Several older compilers are not supported anymore as well, like MSVC 2019 since you can’t easily access from modern GitHub Actions anymore. We’ve mostly avoided removing deprecated items to ease transition, but anything that is producing warnings in 3.0 (which is, with one exception due to a missing but intended warning, the same as things producing warnings in 3.0) might be removed in the future, so please make sure you are deprecation warning free when building.

Other things

We’ve bumped our internal ABI. If you are passing objects between compiled extensions, both should use pybind11 3.0. The conduit feature we added helps, but it’s only helpful one way. We don’t support targeting older ABIs.

FindPython is now the default for CMake builds! We’ve added back-compat variables that should help the transition be seamless; if you explicitly set PYBIND11_FINDPYTHON to ON they won’t be set (and setting it to OFF still works for now). A future version will drop the back-compat variables and the old mode, so please start working on transitioning.

We also now provide dedicated support for the pkgconf PyPI package. If you are using the pybind11 command, it now supports --extension-suffix and has colorful help on Python 3.14+.

We have dedicated support for warnings with py::warnings. We set __file__ on submodules where we can (which improves pickle support), and functions are now pickable. There are lots of other little things for specific cases, feel free to check out the changelog and upgrade guide in the docs!