@@ -65,10 +65,10 @@ helper class that is defined as follows:
65
65
66
66
.. code-block :: cpp
67
67
68
- class PyAnimal : public py::wrapper< Animal> {
68
+ class PyAnimal : public Animal {
69
69
public:
70
70
/* Inherit the constructors */
71
- using py::wrapper< Animal>::wrapper ;
71
+ using Animal::Animal ;
72
72
73
73
/* Trampoline (need one for each virtual function) */
74
74
std::string go(int n_times) override {
@@ -90,15 +90,13 @@ function* slots, which defines the name of function in Python. This is required
90
90
when the C++ and Python versions of the
91
91
function have different names, e.g. ``operator() `` vs ``__call__ ``.
92
92
93
- The base class ``py::wrapper<> `` is optional, but is recommended as it allows us to attach the lifetime of Python objects directly to C++ objects, explained in :ref: `virtual_inheritance_lifetime `.
94
-
95
93
The binding code also needs a few minor adaptations (highlighted):
96
94
97
95
.. code-block :: cpp
98
96
:emphasize-lines: 2,4,5
99
97
100
98
PYBIND11_MODULE(example, m) {
101
- py::class_<Animal, PyAnimal /* <--- trampoline*/> animal(m, "Animal");
99
+ py::class_<Animal, py::wrapper< PyAnimal> /* <--- trampoline*/> animal(m, "Animal");
102
100
animal
103
101
.def(py::init<>())
104
102
.def("go", &Animal::go);
@@ -119,7 +117,7 @@ Bindings should be made against the actual class, not the trampoline helper clas
119
117
120
118
.. code-block :: cpp
121
119
122
- py::class_<Animal, PyAnimal /* <--- trampoline*/> animal(m, "Animal");
120
+ py::class_<Animal, py::wrapper< PyAnimal> /* <--- trampoline*/> animal(m, "Animal");
123
121
animal
124
122
.def(py::init<>())
125
123
.def("go", &PyAnimal::go); /* <--- THIS IS WRONG, use &Animal::go */
@@ -129,6 +127,16 @@ extend ``Animal``, but not ``Dog``: see :ref:`virtual_and_inheritance` for the
129
127
necessary steps required to providing proper overload support for inherited
130
128
classes.
131
129
130
+ The wrapper ``py::wrapper<> `` is optional, but is recommended as it
131
+ allows us to attach the lifetime of Python objects directly to C++ objects,
132
+ explained in :ref: `virtual_inheritance_lifetime `.
133
+
134
+ .. note ::
135
+
136
+ If you do use ``py::wrapper<> `` and you have defined factory
137
+ ``__init__ `` methods, you *must * ensure that the alias variants return new
138
+ instances of ``py::wrapper<Alias> ``, rather than just ``Alias ``.
139
+
132
140
The Python session below shows how to override ``Animal::go `` and invoke it via
133
141
a virtual method call.
134
142
@@ -234,15 +242,15 @@ override the ``name()`` method):
234
242
235
243
.. code-block :: cpp
236
244
237
- class PyAnimal : public py::wrapper< Animal> {
245
+ class PyAnimal : public Animal {
238
246
public:
239
- using py::wrapper< Animal>::wrapper ; // Inherit constructors
247
+ using Animal::Animal ; // Inherit constructors
240
248
std::string go(int n_times) override { PYBIND11_OVERLOAD_PURE(std::string, Animal, go, n_times); }
241
249
std::string name() override { PYBIND11_OVERLOAD(std::string, Animal, name, ); }
242
250
};
243
- class PyDog : public py::wrapper< Dog> {
251
+ class PyDog : public Dog {
244
252
public:
245
- using py::wrapper< Dog>::wrapper ; // Inherit constructors
253
+ using Dog::Dog ; // Inherit constructors
246
254
std::string go(int n_times) override { PYBIND11_OVERLOAD_PURE(std::string, Dog, go, n_times); }
247
255
std::string name() override { PYBIND11_OVERLOAD(std::string, Dog, name, ); }
248
256
std::string bark() override { PYBIND11_OVERLOAD(std::string, Dog, bark, ); }
@@ -262,24 +270,24 @@ declare or override any virtual methods itself:
262
270
.. code-block :: cpp
263
271
264
272
class Husky : public Dog {};
265
- class PyHusky : public py::wrapper< Husky> {
273
+ class PyHusky : public Husky {
266
274
public:
267
- using py::wrapper< Husky>::wrapper ; // Inherit constructors
275
+ using Husky::Husky ; // Inherit constructors
268
276
std::string go(int n_times) override { PYBIND11_OVERLOAD_PURE(std::string, Husky, go, n_times); }
269
277
std::string name() override { PYBIND11_OVERLOAD(std::string, Husky, name, ); }
270
278
std::string bark() override { PYBIND11_OVERLOAD(std::string, Husky, bark, ); }
271
279
};
272
280
273
281
There is, however, a technique that can be used to avoid this duplication
274
282
(which can be especially helpful for a base class with several virtual
275
- methods). The technique (the Curiously Recurring Template Pattern) involves using template trampoline classes, as
283
+ methods). The technique involves using template trampoline classes, as
276
284
follows:
277
285
278
286
.. code-block :: cpp
279
287
280
- template <class AnimalBase = Animal> class PyAnimal : public py::wrapper< AnimalBase> {
288
+ template <class AnimalBase = Animal> class PyAnimal : public AnimalBase {
281
289
public:
282
- using py::wrapper< AnimalBase>::wrapper ; // Inherit constructors
290
+ using AnimalBase::AnimalBase ; // Inherit constructors
283
291
std::string go(int n_times) override { PYBIND11_OVERLOAD_PURE(std::string, AnimalBase, go, n_times); }
284
292
std::string name() override { PYBIND11_OVERLOAD(std::string, AnimalBase, name, ); }
285
293
};
@@ -301,9 +309,9 @@ The classes are then registered with pybind11 using:
301
309
302
310
.. code-block :: cpp
303
311
304
- py::class_<Animal, PyAnimal<>> animal(m, "Animal");
305
- py::class_<Dog, PyDog<>> dog(m, "Dog");
306
- py::class_<Husky, PyDog<Husky>> husky(m, "Husky");
312
+ py::class_<Animal, py::wrapper< PyAnimal<> >> animal(m, "Animal");
313
+ py::class_<Dog, py::wrapper< PyDog<> >> dog(m, "Dog");
314
+ py::class_<Husky, py::wrapper< PyDog<Husky> >> husky(m, "Husky");
307
315
// ... add animal, dog, husky definitions
308
316
309
317
Note that ``Husky `` did not require a dedicated trampoline template class at
@@ -324,6 +332,12 @@ can now create a python class that inherits from ``Dog``:
324
332
See the file :file: `tests/test_virtual_functions.cpp ` for complete examples
325
333
using both the duplication and templated trampoline approaches.
326
334
335
+ .. note ::
336
+
337
+ If you do not want to specify ``py::wrapper<> `` for each type, you
338
+ can have ``PyAnimal `` inherit from ``py::wrapper<> ``. Pybind will
339
+ detect if ``py::wrapper<> `` is present at any point in the chain.
340
+
327
341
.. _extended_aliases :
328
342
329
343
Extended trampoline class functionality
@@ -1051,10 +1065,10 @@ For this example, we will build upon the above code for ``Animal`` with alias ``
1051
1065
virtual std::string go(int n_times) = 0;
1052
1066
};
1053
1067
1054
- class PyAnimal : public py::wrapper< Animal> {
1068
+ class PyAnimal : public Animal {
1055
1069
public:
1056
1070
/* Inherit the constructors */
1057
- using py::wrapper< Animal>::wrapper ;
1071
+ using Animal::Animal ;
1058
1072
std::string go(int n_times) override {
1059
1073
PYBIND11_OVERLOAD_PURE(std::string, Animal, go, n_times);
1060
1074
}
@@ -1077,7 +1091,7 @@ And the following bindings:
1077
1091
.. code-block :: cpp
1078
1092
1079
1093
PYBIND11_MODULE(example, m) {
1080
- py::class_<Animal, PyAnimal, std::shared_ptr<Animal>> animal(m, "Animal");
1094
+ py::class_<Animal, py::wrapper< PyAnimal> , std::shared_ptr<Animal>> animal(m, "Animal");
1081
1095
animal
1082
1096
.def(py::init<>())
1083
1097
.def("go", &Animal::go);
0 commit comments