Files
pybind11/tests/test_class_sp_trampoline_weak_ptr.cpp
Ralf W. Grosse-Kunstleve 4638e017b6 Modify py::trampoline_self_life_support semantics: if trampoline class does not inherit from this class, preserve established Inheritance Slicing behavior.
rwgk reached this point with the help of ChatGPT:

* https://chatgpt.com/share/68056498-7d94-8008-8ff0-232e2aba451c

The only production code change in this commit is:

```
diff --git a/include/pybind11/detail/type_caster_base.h b/include/pybind11/detail/type_caster_base.h
index d4f9a41e..f3d45301 100644
--- a/include/pybind11/detail/type_caster_base.h
+++ b/include/pybind11/detail/type_caster_base.h
@@ -776,6 +776,14 @@ struct load_helper : value_and_holder_helper {
                 if (released_ptr) {
                     return std::shared_ptr<T>(released_ptr, type_raw_ptr);
                 }
+                auto *self_life_support
+                    = dynamic_raw_ptr_cast_if_possible<trampoline_self_life_support>(type_raw_ptr);
+                if (self_life_support == nullptr) {
+                    std::shared_ptr<void> void_shd_ptr = hld.template as_shared_ptr<void>();
+                    std::shared_ptr<T> to_be_released(void_shd_ptr, type_raw_ptr);
+                    vptr_gd_ptr->released_ptr = to_be_released;
+                    return to_be_released;
+                }
                 std::shared_ptr<T> to_be_released(
                     type_raw_ptr, shared_ptr_trampoline_self_life_support(loaded_v_h.inst));
                 vptr_gd_ptr->released_ptr = to_be_released;
```
2025-04-20 14:14:47 -07:00

83 lines
2.0 KiB
C++

// Copyright (c) 2025 The Pybind Development Team.
// All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#include "pybind11_tests.h"
#include <memory>
namespace pybind11_tests {
namespace class_sp_trampoline_weak_ptr {
struct VirtBase {
virtual ~VirtBase() = default;
virtual int get_code() { return 100; }
};
struct PyVirtBase : VirtBase, py::trampoline_self_life_support {
using VirtBase::VirtBase;
int get_code() override { PYBIND11_OVERRIDE(int, VirtBase, get_code); }
~PyVirtBase() override {
fflush(stderr);
printf("\nLOOOK ~PyVirtBase()\n");
fflush(stdout);
}
};
struct WpOwner {
void set_wp(const std::shared_ptr<VirtBase> &sp) { wp = sp; }
int get_code() {
auto sp = wp.lock();
if (!sp) {
return -999;
}
return sp->get_code();
}
private:
std::weak_ptr<VirtBase> wp;
};
struct SpOwner {
void set_sp(const std::shared_ptr<VirtBase> &sp) { this->sp = sp; }
int get_code() {
if (!sp) {
return -888;
}
return sp->get_code();
}
private:
std::shared_ptr<VirtBase> sp;
};
std::shared_ptr<VirtBase> pass_through_sp_VirtBase(const std::shared_ptr<VirtBase> &sp) {
return sp;
}
} // namespace class_sp_trampoline_weak_ptr
} // namespace pybind11_tests
using namespace pybind11_tests::class_sp_trampoline_weak_ptr;
TEST_SUBMODULE(class_sp_trampoline_weak_ptr, m) {
py::class_<VirtBase, std::shared_ptr<VirtBase>, PyVirtBase>(m, "VirtBase")
.def(py::init<>())
.def("get_code", &VirtBase::get_code);
py::class_<WpOwner>(m, "WpOwner")
.def(py::init<>())
.def("set_wp", &WpOwner::set_wp)
.def("get_code", &WpOwner::get_code);
py::class_<SpOwner>(m, "SpOwner")
.def(py::init<>())
.def("set_sp", &SpOwner::set_sp)
.def("get_code", &SpOwner::get_code);
m.def("pass_through_sp_VirtBase", pass_through_sp_VirtBase);
}