Skip to content

Commit

Permalink
Merge branch 'pybind:master' into master
Browse files Browse the repository at this point in the history
  • Loading branch information
sun1638650145 authored Mar 6, 2025
2 parents 3322bce + 2943a27 commit ee597ca
Show file tree
Hide file tree
Showing 66 changed files with 5,522 additions and 158 deletions.
11 changes: 11 additions & 0 deletions .codespell-ignore-lines
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,17 @@ template <op_id id, op_type ot, typename L, typename R>
template <detail::op_id id, detail::op_type ot, typename L, typename R, typename... Extra>
class_ &def(const detail::op_<id, ot, L, R> &op, const Extra &...extra) {
class_ &def_cast(const detail::op_<id, ot, L, R> &op, const Extra &...extra) {
int valu;
explicit movable_int(int v) : valu{v} {}
movable_int(movable_int &&other) noexcept : valu(other.valu) { other.valu = 91; }
explicit indestructible_int(int v) : valu{v} {}
REQUIRE(hld.as_raw_ptr_unowned<zombie>()->valu == 19);
REQUIRE(othr.valu == 19);
REQUIRE(orig.valu == 91);
(m.pass_valu, "Valu", "pass_valu:Valu(_MvCtor)*_CpCtor"),
atyp_valu rtrn_valu() { atyp_valu obj{"Valu"}; return obj; }
assert m.atyp_valu().get_mtxt() == "Valu"
// valu(e), ref(erence), ptr or p (pointer), r = rvalue, m = mutable, c = const,
@pytest.mark.parametrize("access", ["ro", "rw", "static_ro", "static_rw"])
struct IntStruct {
explicit IntStruct(int v) : value(v){};
Expand Down
14 changes: 14 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,20 @@ jobs:
# Extra ubuntu latest job
- runs-on: ubuntu-latest
python: '3.11'
# Run tests with py::smart_holder as the default holder
# with recent (or ideally latest) released Python version.
- runs-on: ubuntu-latest
python: '3.12'
args: >
-DCMAKE_CXX_FLAGS="-DPYBIND11_RUN_TESTING_WITH_SMART_HOLDER_AS_DEFAULT_BUT_NEVER_USE_IN_PRODUCTION_PLEASE"
- runs-on: macos-13
python: '3.12'
args: >
-DCMAKE_CXX_FLAGS="-DPYBIND11_RUN_TESTING_WITH_SMART_HOLDER_AS_DEFAULT_BUT_NEVER_USE_IN_PRODUCTION_PLEASE"
- runs-on: windows-2022
python: '3.12'
args: >
-DCMAKE_CXX_FLAGS="/DPYBIND11_RUN_TESTING_WITH_SMART_HOLDER_AS_DEFAULT_BUT_NEVER_USE_IN_PRODUCTION_PLEASE /GR /EHsc"
exclude:
# The setup-python action currently doesn't have graalpy for windows
- python: 'graalpy-24.1'
Expand Down
2 changes: 2 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ repos:
- id: mixed-line-ending
- id: requirements-txt-fixer
- id: trailing-whitespace
exclude: \.patch?$

# Also code format the docs
- repo: https://github.com/adamchainz/blacken-docs
Expand All @@ -90,6 +91,7 @@ repos:
rev: "v1.5.5"
hooks:
- id: remove-tabs
exclude: (^docs/.*|\.patch)?$

# Avoid directional quotes
- repo: https://github.com/sirosen/texthooks
Expand Down
4 changes: 4 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -131,10 +131,13 @@ set(PYBIND11_HEADERS
include/pybind11/detail/common.h
include/pybind11/detail/cpp_conduit.h
include/pybind11/detail/descr.h
include/pybind11/detail/dynamic_raw_ptr_cast_if_possible.h
include/pybind11/detail/init.h
include/pybind11/detail/internals.h
include/pybind11/detail/struct_smart_holder.h
include/pybind11/detail/type_caster_base.h
include/pybind11/detail/typeid.h
include/pybind11/detail/using_smart_holder.h
include/pybind11/detail/value_and_holder.h
include/pybind11/detail/exception_translation.h
include/pybind11/attr.h
Expand Down Expand Up @@ -164,6 +167,7 @@ set(PYBIND11_HEADERS
include/pybind11/stl.h
include/pybind11/stl_bind.h
include/pybind11/stl/filesystem.h
include/pybind11/trampoline_self_life_support.h
include/pybind11/type_caster_pyobject_ptr.h
include/pybind11/typing.h
include/pybind11/warnings.h)
Expand Down
35 changes: 29 additions & 6 deletions README.rst
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
.. figure:: https://github.com/pybind/pybind11/raw/master/docs/pybind11-logo.png
:alt: pybind11 logo

**pybind11 — Seamless operability between C++11 and Python**
**pybind11 (v3) — Seamless interoperability between C++ and Python**

|Latest Documentation Status| |Stable Documentation Status| |Gitter chat| |GitHub Discussions| |CI| |Build status|

Expand Down Expand Up @@ -134,11 +134,34 @@ About

This project was created by `Wenzel
Jakob <http://rgl.epfl.ch/people/wjakob>`_. Significant features and/or
improvements to the code were contributed by Jonas Adler, Lori A. Burns,
Sylvain Corlay, Eric Cousineau, Aaron Gokaslan, Ralf Grosse-Kunstleve, Trent Houliston, Axel
Huebl, @hulucc, Yannick Jadoul, Sergey Lyskov, Johan Mabille, Tomasz Miąsko,
Dean Moldovan, Ben Pritchard, Jason Rhinelander, Boris Schäling, Pim
Schellart, Henry Schreiner, Ivan Smirnov, Boris Staletic, and Patrick Stewart.
improvements to the code were contributed by
Jonas Adler,
Lori A. Burns,
Sylvain Corlay,
Eric Cousineau,
Aaron Gokaslan,
Ralf Grosse-Kunstleve,
Trent Houliston,
Axel Huebl,
@hulucc,
Yannick Jadoul,
Sergey Lyskov,
Johan Mabille,
Tomasz Miąsko,
Dean Moldovan,
Ben Pritchard,
Jason Rhinelander,
Boris Schäling,
Pim Schellart,
Henry Schreiner,
Ivan Smirnov,
Dustin Spicuzza,
Boris Staletic,
Ethan Steinberg,
Patrick Stewart,
Ivor Wanders,
and
Xiaofei Wang.

We thank Google for a generous financial contribution to the continuous
integration infrastructure used by this project.
Expand Down
4 changes: 2 additions & 2 deletions docs/advanced/cast/stl.rst
Original file line number Diff line number Diff line change
Expand Up @@ -169,8 +169,8 @@ macro must be specified at the top level (and outside of any namespaces), since
it adds a template instantiation of ``type_caster``. If your binding code consists of
multiple compilation units, it must be present in every file (typically via a
common header) preceding any usage of ``std::vector<int>``. Opaque types must
also have a corresponding ``class_`` declaration to associate them with a name
in Python, and to define a set of available operations, e.g.:
also have a corresponding ``py::class_`` declaration to associate them with a
name in Python, and to define a set of available operations, e.g.:

.. code-block:: cpp
Expand Down
73 changes: 44 additions & 29 deletions docs/advanced/classes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ helper class that is defined as follows:

.. code-block:: cpp
class PyAnimal : public Animal {
class PyAnimal : public Animal, py::trampoline_self_life_support {
public:
/* Inherit the constructors */
using Animal::Animal;
Expand All @@ -80,6 +80,18 @@ helper class that is defined as follows:
}
};
The ``py::trampoline_self_life_support`` base class is needed to ensure
that a ``std::unique_ptr`` can safely be passed between Python and C++. To
steer clear of notorious pitfalls (e.g. inheritance slicing), it is best
practice to always use the base class, in combination with
``py::smart_holder``.

.. note::
For completeness, the base class has no effect if a holder other than
``py::smart_holder`` used, including the default ``std::unique_ptr<T>``.
Please think twice, though, the pitfalls are very real, and the overhead
for using the safer ``py::smart_holder`` is very likely to be in the noise.

The macro :c:macro:`PYBIND11_OVERRIDE_PURE` should be used for pure virtual
functions, and :c:macro:`PYBIND11_OVERRIDE` should be used for functions which have
a default implementation. There are also two alternate macros
Expand All @@ -95,18 +107,18 @@ The binding code also needs a few minor adaptations (highlighted):
:emphasize-lines: 2,3
PYBIND11_MODULE(example, m) {
py::class_<Animal, PyAnimal /* <--- trampoline*/>(m, "Animal")
py::class_<Animal, PyAnimal /* <--- trampoline */, py::smart_holder>(m, "Animal")
.def(py::init<>())
.def("go", &Animal::go);
py::class_<Dog, Animal>(m, "Dog")
py::class_<Dog, Animal, py::smart_holder>(m, "Dog")
.def(py::init<>());
m.def("call_go", &call_go);
}
Importantly, pybind11 is made aware of the trampoline helper class by
specifying it as an extra template argument to :class:`class_`. (This can also
specifying it as an extra template argument to ``py::class_``. (This can also
be combined with other template arguments such as a custom holder type; the
order of template types does not matter). Following this, we are able to
define a constructor as usual.
Expand All @@ -116,9 +128,9 @@ Bindings should be made against the actual class, not the trampoline helper clas
.. code-block:: cpp
:emphasize-lines: 3
py::class_<Animal, PyAnimal /* <--- trampoline*/>(m, "Animal");
py::class_<Animal, PyAnimal /* <--- trampoline */, py::smart_holder>(m, "Animal");
.def(py::init<>())
.def("go", &PyAnimal::go); /* <--- THIS IS WRONG, use &Animal::go */
.def("go", &Animal::go); /* <--- DO NOT USE &PyAnimal::go HERE */
Note, however, that the above is sufficient for allowing python classes to
extend ``Animal``, but not ``Dog``: see :ref:`virtual_and_inheritance` for the
Expand Down Expand Up @@ -244,13 +256,13 @@ override the ``name()`` method):

.. code-block:: cpp
class PyAnimal : public Animal {
class PyAnimal : public Animal, py::trampoline_self_life_support {
public:
using Animal::Animal; // Inherit constructors
std::string go(int n_times) override { PYBIND11_OVERRIDE_PURE(std::string, Animal, go, n_times); }
std::string name() override { PYBIND11_OVERRIDE(std::string, Animal, name, ); }
};
class PyDog : public Dog {
class PyDog : public Dog, py::trampoline_self_life_support {
public:
using Dog::Dog; // Inherit constructors
std::string go(int n_times) override { PYBIND11_OVERRIDE(std::string, Dog, go, n_times); }
Expand All @@ -272,7 +284,7 @@ declare or override any virtual methods itself:
.. code-block:: cpp
class Husky : public Dog {};
class PyHusky : public Husky {
class PyHusky : public Husky, py::trampoline_self_life_support {
public:
using Husky::Husky; // Inherit constructors
std::string go(int n_times) override { PYBIND11_OVERRIDE_PURE(std::string, Husky, go, n_times); }
Expand All @@ -287,13 +299,15 @@ follows:

.. code-block:: cpp
template <class AnimalBase = Animal> class PyAnimal : public AnimalBase {
template <class AnimalBase = Animal>
class PyAnimal : public AnimalBase, py::trampoline_self_life_support {
public:
using AnimalBase::AnimalBase; // Inherit constructors
std::string go(int n_times) override { PYBIND11_OVERRIDE_PURE(std::string, AnimalBase, go, n_times); }
std::string name() override { PYBIND11_OVERRIDE(std::string, AnimalBase, name, ); }
};
template <class DogBase = Dog> class PyDog : public PyAnimal<DogBase> {
template <class DogBase = Dog>
class PyDog : public PyAnimal<DogBase>, py::trampoline_self_life_support {
public:
using PyAnimal<DogBase>::PyAnimal; // Inherit constructors
// Override PyAnimal's pure virtual go() with a non-pure one:
Expand All @@ -311,9 +325,9 @@ The classes are then registered with pybind11 using:

.. code-block:: cpp
py::class_<Animal, PyAnimal<>> animal(m, "Animal");
py::class_<Dog, Animal, PyDog<>> dog(m, "Dog");
py::class_<Husky, Dog, PyDog<Husky>> husky(m, "Husky");
py::class_<Animal, PyAnimal<>, py::smart_holder> animal(m, "Animal");
py::class_<Dog, Animal, PyDog<>, py::smart_holder> dog(m, "Dog");
py::class_<Husky, Dog, PyDog<Husky>, py::smart_holder> husky(m, "Husky");
// ... add animal, dog, husky definitions
Note that ``Husky`` did not require a dedicated trampoline template class at
Expand Down Expand Up @@ -499,12 +513,12 @@ an alias:
// ...
virtual ~Example() = default;
};
class PyExample : public Example {
class PyExample : public Example, py::trampoline_self_life_support {
public:
using Example::Example;
PyExample(Example &&base) : Example(std::move(base)) {}
};
py::class_<Example, PyExample>(m, "Example")
py::class_<Example, PyExample, py::smart_holder>(m, "Example")
// Returns an Example pointer. If a PyExample is needed, the Example
// instance will be moved via the extra constructor in PyExample, above.
.def(py::init([]() { return new Example(); }))
Expand Down Expand Up @@ -550,9 +564,10 @@ pybind11. The underlying issue is that the ``std::unique_ptr`` holder type that
is responsible for managing the lifetime of instances will reference the
destructor even if no deallocations ever take place. In order to expose classes
with private or protected destructors, it is possible to override the holder
type via a holder type argument to ``class_``. Pybind11 provides a helper class
``py::nodelete`` that disables any destructor invocations. In this case, it is
crucial that instances are deallocated on the C++ side to avoid memory leaks.
type via a holder type argument to ``py::class_``. Pybind11 provides a helper
class ``py::nodelete`` that disables any destructor invocations. In this case,
it is crucial that instances are deallocated on the C++ side to avoid memory
leaks.

.. code-block:: cpp
Expand Down Expand Up @@ -871,7 +886,7 @@ Multiple Inheritance

pybind11 can create bindings for types that derive from multiple base types
(aka. *multiple inheritance*). To do so, specify all bases in the template
arguments of the ``class_`` declaration:
arguments of the ``py::class_`` declaration:

.. code-block:: cpp
Expand Down Expand Up @@ -946,23 +961,23 @@ because of conflicting definitions on the external type:
// dogs.cpp
// Binding for external library class:
py::class<pets::Pet>(m, "Pet")
py::class_<pets::Pet>(m, "Pet")
.def("name", &pets::Pet::name);
// Binding for local extension class:
py::class<Dog, pets::Pet>(m, "Dog")
py::class_<Dog, pets::Pet>(m, "Dog")
.def(py::init<std::string>());
.. code-block:: cpp
// cats.cpp, in a completely separate project from the above dogs.cpp.
// Binding for external library class:
py::class<pets::Pet>(m, "Pet")
py::class_<pets::Pet>(m, "Pet")
.def("get_name", &pets::Pet::name);
// Binding for local extending class:
py::class<Cat, pets::Pet>(m, "Cat")
py::class_<Cat, pets::Pet>(m, "Cat")
.def(py::init<std::string>());
.. code-block:: pycon
Expand All @@ -980,13 +995,13 @@ the ``py::class_`` constructor:
.. code-block:: cpp
// Pet binding in dogs.cpp:
py::class<pets::Pet>(m, "Pet", py::module_local())
py::class_<pets::Pet>(m, "Pet", py::module_local())
.def("name", &pets::Pet::name);
.. code-block:: cpp
// Pet binding in cats.cpp:
py::class<pets::Pet>(m, "Pet", py::module_local())
py::class_<pets::Pet>(m, "Pet", py::module_local())
.def("get_name", &pets::Pet::name);
This makes the Python-side ``dogs.Pet`` and ``cats.Pet`` into distinct classes,
Expand Down Expand Up @@ -1104,7 +1119,7 @@ described trampoline:
virtual int foo() const { return 42; }
};
class Trampoline : public A {
class Trampoline : public A, py::trampoline_self_life_support {
public:
int foo() const override { PYBIND11_OVERRIDE(int, A, foo, ); }
};
Expand All @@ -1114,7 +1129,7 @@ described trampoline:
using A::foo;
};
py::class_<A, Trampoline>(m, "A") // <-- `Trampoline` here
py::class_<A, Trampoline, py::smart_holder>(m, "A") // <-- `Trampoline` here
.def("foo", &Publicist::foo); // <-- `Publicist` here, not `Trampoline`!
Binding final classes
Expand Down Expand Up @@ -1195,7 +1210,7 @@ but once again each instantiation must be explicitly specified:
T fn(V v);
};
py::class<MyClass<int>>(m, "MyClassT")
py::class_<MyClass<int>>(m, "MyClassT")
.def("fn", &MyClass<int>::fn<std::string>);
Custom automatic downcasters
Expand Down
Loading

0 comments on commit ee597ca

Please sign in to comment.