7
7
namespace pybind11_tests {
8
8
namespace class_sh_void_ptr_capsule {
9
9
10
- // Without the helper we will run into a type_caster::load recursion.
11
- // This is because whenever the type_caster::load is called, it checks
12
- // whether the object defines an `as_` method that returns the void pointer
13
- // capsule. If yes, it calls the method. But in the following testcases, those
14
- // `as_` methods are defined with pybind11, which implicitly takes the object
15
- // itself as the first parameter. Therefore calling those methods causes loading
16
- // the object again, which causes infinite recursion.
17
- // This test is unusual in the sense that the void pointer capsules are meant to
18
- // be provided by objects wrapped with systems other than pybind11
19
- // (i.e. having to avoid the recursion is an artificial problem, not the norm).
20
- // Conveniently, the helper also serves to keep track of `capsule_generated`.
10
+ // Conveniently, the helper serves to keep track of `capsule_generated`.
21
11
struct HelperBase {
22
12
HelperBase () = default ;
23
13
HelperBase (const HelperBase &) = delete ;
@@ -65,6 +55,12 @@ struct AsAnotherObject : public HelperBase {
65
55
}
66
56
};
67
57
58
+ // https://github.com/pybind/pybind11/issues/3788
59
+ struct TypeWithGetattr {
60
+ TypeWithGetattr () = default ;
61
+ int get_42 () const { return 42 ; }
62
+ };
63
+
68
64
int get_from_valid_capsule (const Valid *c) { return c->get (); }
69
65
70
66
int get_from_shared_ptr_valid_capsule (const std::shared_ptr<Valid> &c) { return c->get (); }
@@ -83,6 +79,7 @@ PYBIND11_SMART_HOLDER_TYPE_CASTERS(pybind11_tests::class_sh_void_ptr_capsule::Va
83
79
PYBIND11_SMART_HOLDER_TYPE_CASTERS(pybind11_tests::class_sh_void_ptr_capsule::NoConversion)
84
80
PYBIND11_SMART_HOLDER_TYPE_CASTERS(pybind11_tests::class_sh_void_ptr_capsule::NoCapsuleReturned)
85
81
PYBIND11_SMART_HOLDER_TYPE_CASTERS(pybind11_tests::class_sh_void_ptr_capsule::AsAnotherObject)
82
+ PYBIND11_SMART_HOLDER_TYPE_CASTERS(pybind11_tests::class_sh_void_ptr_capsule::TypeWithGetattr)
86
83
87
84
TEST_SUBMODULE(class_sh_void_ptr_capsule, m) {
88
85
using namespace pybind11_tests ::class_sh_void_ptr_capsule;
@@ -94,10 +91,8 @@ TEST_SUBMODULE(class_sh_void_ptr_capsule, m) {
94
91
95
92
py::classh<Valid, HelperBase>(m, " Valid" )
96
93
.def (py::init<>())
97
- .def (" as_pybind11_tests_class_sh_void_ptr_capsule_Valid" , [](HelperBase *self) {
98
- auto *obj = dynamic_cast <Valid *>(self);
99
- assert (obj != nullptr );
100
- PyObject *capsule = obj->as_pybind11_tests_class_sh_void_ptr_capsule_Valid ();
94
+ .def (" as_pybind11_tests_class_sh_void_ptr_capsule_Valid" , [](Valid &self) {
95
+ PyObject *capsule = self.as_pybind11_tests_class_sh_void_ptr_capsule_Valid ();
101
96
return pybind11::reinterpret_steal<py::capsule>(capsule);
102
97
});
103
98
@@ -106,20 +101,16 @@ TEST_SUBMODULE(class_sh_void_ptr_capsule, m) {
106
101
py::classh<NoCapsuleReturned, HelperBase>(m, " NoCapsuleReturned" )
107
102
.def (py::init<>())
108
103
.def (" as_pybind11_tests_class_sh_void_ptr_capsule_NoCapsuleReturned" ,
109
- [](HelperBase *self) {
110
- auto *obj = dynamic_cast <NoCapsuleReturned *>(self);
111
- assert (obj != nullptr );
104
+ [](NoCapsuleReturned &self) {
112
105
PyObject *capsule
113
- = obj-> as_pybind11_tests_class_sh_void_ptr_capsule_NoCapsuleReturned ();
106
+ = self. as_pybind11_tests_class_sh_void_ptr_capsule_NoCapsuleReturned ();
114
107
return pybind11::reinterpret_steal<py::capsule>(capsule);
115
108
});
116
109
117
110
py::classh<AsAnotherObject, HelperBase>(m, " AsAnotherObject" )
118
111
.def (py::init<>())
119
- .def (" as_pybind11_tests_class_sh_void_ptr_capsule_Valid" , [](HelperBase *self) {
120
- auto *obj = dynamic_cast <AsAnotherObject *>(self);
121
- assert (obj != nullptr );
122
- PyObject *capsule = obj->as_pybind11_tests_class_sh_void_ptr_capsule_Valid ();
112
+ .def (" as_pybind11_tests_class_sh_void_ptr_capsule_Valid" , [](AsAnotherObject &self) {
113
+ PyObject *capsule = self.as_pybind11_tests_class_sh_void_ptr_capsule_Valid ();
123
114
return pybind11::reinterpret_steal<py::capsule>(capsule);
124
115
});
125
116
@@ -128,4 +119,10 @@ TEST_SUBMODULE(class_sh_void_ptr_capsule, m) {
128
119
m.def (" get_from_unique_ptr_valid_capsule" , &get_from_unique_ptr_valid_capsule);
129
120
m.def (" get_from_no_conversion_capsule" , &get_from_no_conversion_capsule);
130
121
m.def (" get_from_no_capsule_returned" , &get_from_no_capsule_returned);
122
+
123
+ py::classh<TypeWithGetattr>(m, " TypeWithGetattr" )
124
+ .def (py::init<>())
125
+ .def (" get_42" , &TypeWithGetattr::get_42)
126
+ .def (" __getattr__" ,
127
+ [](TypeWithGetattr &, const std::string &key) { return " GetAttr: " + key; });
131
128
}
0 commit comments