
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!