Skip to content

Commit 6e213c9

Browse files
author
Wenzel Jakob
committed
improved shared pointer support (fixes #14)
1 parent 5e90fa4 commit 6e213c9

File tree

6 files changed

+240
-137
lines changed

6 files changed

+240
-137
lines changed

docs/advanced.rst

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -457,6 +457,14 @@ be declared at the top level before any binding code:
457457
demonstrates how to work with custom reference-counting holder types in
458458
more detail.
459459

460+
.. warning::
461+
462+
To ensure correct reference counting among Python and C++, the use of
463+
``std::shared_ptr<T>`` as a holder type requires that ``T`` inherits from
464+
``std::enable_shared_from_this<T>`` (see cppreference_ for details).
465+
466+
.. _cppreference: http://en.cppreference.com/w/cpp/memory/enable_shared_from_this
467+
460468
.. _custom_constructors:
461469

462470
Custom constructors

example/example8.cpp

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,36 @@ class MyObject : public Object {
3131
int value;
3232
};
3333

34+
class MyObject2 : public std::enable_shared_from_this<MyObject2> {
35+
public:
36+
MyObject2(int value) : value(value) {
37+
std::cout << toString() << " constructor" << std::endl;
38+
}
39+
40+
std::string toString() const {
41+
return "MyObject2[" + std::to_string(value) + "]";
42+
}
43+
44+
virtual ~MyObject2() {
45+
std::cout << toString() << " destructor" << std::endl;
46+
}
47+
48+
private:
49+
int value;
50+
};
51+
3452
/// Make pybind aware of the ref-counted wrapper type
3553
PYBIND11_DECLARE_HOLDER_TYPE(T, ref<T>);
54+
PYBIND11_DECLARE_HOLDER_TYPE(T, std::shared_ptr<T>);
3655

3756
Object *make_object_1() { return new MyObject(1); }
3857
ref<Object> make_object_2() { return new MyObject(2); }
3958
MyObject *make_myobject_4() { return new MyObject(4); }
4059
ref<MyObject> make_myobject_5() { return new MyObject(5); }
4160

61+
MyObject2 *make_myobject2_1() { return new MyObject2(1); }
62+
std::shared_ptr<MyObject2> make_myobject2_2() { return std::make_shared<MyObject2>(2); }
63+
4264
void print_object_1(const Object *obj) { std::cout << obj->toString() << std::endl; }
4365
void print_object_2(ref<Object> obj) { std::cout << obj->toString() << std::endl; }
4466
void print_object_3(const ref<Object> &obj) { std::cout << obj->toString() << std::endl; }
@@ -49,6 +71,11 @@ void print_myobject_2(ref<MyObject> obj) { std::cout << obj->toString() << std::
4971
void print_myobject_3(const ref<MyObject> &obj) { std::cout << obj->toString() << std::endl; }
5072
void print_myobject_4(const ref<MyObject> *obj) { std::cout << (*obj)->toString() << std::endl; }
5173

74+
void print_myobject2_1(const MyObject2 *obj) { std::cout << obj->toString() << std::endl; }
75+
void print_myobject2_2(std::shared_ptr<MyObject2> obj) { std::cout << obj->toString() << std::endl; }
76+
void print_myobject2_3(const std::shared_ptr<MyObject2> &obj) { std::cout << obj->toString() << std::endl; }
77+
void print_myobject2_4(const std::shared_ptr<MyObject2> *obj) { std::cout << (*obj)->toString() << std::endl; }
78+
5279
void init_ex8(py::module &m) {
5380
py::class_<Object, ref<Object>> obj(m, "Object");
5481
obj.def("getRefCount", &Object::getRefCount);
@@ -69,5 +96,14 @@ void init_ex8(py::module &m) {
6996
m.def("print_myobject_3", &print_myobject_3);
7097
m.def("print_myobject_4", &print_myobject_4);
7198

99+
py::class_<MyObject2, std::shared_ptr<MyObject2>>(m, "MyObject2")
100+
.def(py::init<int>());
101+
m.def("make_myobject2_1", &make_myobject2_1);
102+
m.def("make_myobject2_2", &make_myobject2_2);
103+
m.def("print_myobject2_1", &print_myobject2_1);
104+
m.def("print_myobject2_2", &print_myobject2_2);
105+
m.def("print_myobject2_3", &print_myobject2_3);
106+
m.def("print_myobject2_4", &print_myobject2_4);
107+
72108
py::implicitly_convertible<py::int_, MyObject>();
73109
}

example/example8.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
from example import make_object_2
99
from example import make_myobject_4
1010
from example import make_myobject_5
11+
from example import make_myobject2_1
12+
from example import make_myobject2_2
1113
from example import print_object_1
1214
from example import print_object_2
1315
from example import print_object_3
@@ -16,6 +18,10 @@
1618
from example import print_myobject_2
1719
from example import print_myobject_3
1820
from example import print_myobject_4
21+
from example import print_myobject2_1
22+
from example import print_myobject2_2
23+
from example import print_myobject2_3
24+
from example import print_myobject2_4
1925

2026
for o in [make_object_1(), make_object_2(), MyObject(3)]:
2127
print("Reference count = %i" % o.getRefCount())
@@ -35,3 +41,11 @@
3541
print_myobject_2(o)
3642
print_myobject_3(o)
3743
print_myobject_4(o)
44+
45+
46+
for o in [make_myobject2_1(), make_myobject2_2()]:
47+
print(o)
48+
print_myobject2_1(o)
49+
print_myobject2_2(o)
50+
print_myobject2_3(o)
51+
print_myobject2_4(o)

0 commit comments

Comments
 (0)