1 // Copyright David Abrahams 2002.
2 // Distributed under the Boost Software License, Version 1.0. (See
3 // accompanying file LICENSE_1_0.txt or copy at
4 // http://www.boost.org/LICENSE_1_0.txt)
5 #include <boost/python/module.hpp>
6 #include <boost/python/def.hpp>
7 #include <boost/python/return_value_policy.hpp>
8 #include <boost/python/manage_new_object.hpp>
9 #include <boost/python/return_internal_reference.hpp>
10 #include <boost/python/class.hpp>
11
12 using namespace boost::python;
13
14 int a_instances = 0;
15
num_a_instances()16 int num_a_instances() { return a_instances; }
17
18 struct inner
19 {
innerinner20 inner(std::string const& s)
21 : s(s)
22 {}
23
changeinner24 void change(std::string const& new_s)
25 {
26 this->s = new_s;
27 }
28
29 std::string s;
30 };
31
32 struct Base
33 {
~BaseBase34 virtual ~Base() {}
35 };
36
37 struct A : Base
38 {
AA39 A(std::string const& s)
40 : x(s)
41 {
42 ++a_instances;
43 }
44
~AA45 ~A()
46 {
47 --a_instances;
48 }
49
contentA50 std::string content() const
51 {
52 return x.s;
53 }
54
get_innerA55 inner& get_inner()
56 {
57 return x;
58 }
59
60 inner x;
61 };
62
63 struct B
64 {
BB65 B() : x(0) {}
BB66 B(A* x_) : x(x_) {}
67
adoptB68 inner const* adopt(A* _x) { this->x = _x; return &_x->get_inner(); }
69
a_contentB70 std::string a_content()
71 {
72 return x ? x->content() : std::string("empty");
73 }
74
75 A* x;
76 };
77
78
create(std::string const & s)79 A* create(std::string const& s)
80 {
81 return new A(s);
82 }
83
as_A(Base * b)84 A* as_A(Base* b)
85 {
86 return dynamic_cast<A*>(b);
87 }
88
BOOST_PYTHON_MODULE(test_pointer_adoption_ext)89 BOOST_PYTHON_MODULE(test_pointer_adoption_ext)
90 {
91 def("num_a_instances", num_a_instances);
92
93 // Specify the manage_new_object return policy to take
94 // ownership of create's result
95 def("create", create, return_value_policy<manage_new_object>());
96
97 def("as_A", as_A, return_internal_reference<>());
98
99 class_<Base>("Base")
100 ;
101
102 class_<A, bases<Base> >("A", no_init)
103 .def("content", &A::content)
104 .def("get_inner", &A::get_inner, return_internal_reference<>())
105 ;
106
107 class_<inner>("inner", no_init)
108 .def("change", &inner::change)
109 ;
110
111 class_<B>("B")
112 .def(init<A*>()[with_custodian_and_ward_postcall<1,2>()])
113
114 .def("adopt", &B::adopt
115 // Adopt returns a pointer referring to a subobject of its 2nd argument (1st being "self")
116 , return_internal_reference<2
117 // Meanwhile, self holds a reference to the 2nd argument.
118 , with_custodian_and_ward<1,2> >()
119 )
120
121 .def("a_content", &B::a_content)
122 ;
123 }
124
125 #include "module_tail.cpp"
126