• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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