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/class.hpp>
7 #include <boost/python/return_value_policy.hpp>
8 #include <boost/python/manage_new_object.hpp>
9 #include <boost/python/reference_existing_object.hpp>
10 #include <boost/python/call_method.hpp>
11 #include <boost/python/pure_virtual.hpp>
12 #include <boost/python/def.hpp>
13 #include <boost/utility.hpp>
14 
15 using namespace boost::python;
16 
17 struct Callback
18 {
CallbackCallback19     Callback(PyObject* o) : mSelf(o) {}
20     PyObject* mSelf;
21 };
22 
23 struct P
24 {
~PP25     virtual ~P(){}
26     virtual std::string f() = 0;
gP27     std::string g() { return "P::g()"; }
28 };
29 
30 struct PCallback : P, Callback
31 {
PCallbackPCallback32     PCallback (PyObject* self) : Callback(self) {}
33 
fPCallback34     std::string f()
35     {
36         return call_method<std::string>(mSelf, "f");
37     }
38 };
39 
40 struct Q : virtual P
41 {
fQ42     std::string f() { return "Q::f()"; }
43 };
44 
45 struct A
46 {
~AA47     virtual ~A(){}
fA48     virtual std::string f() { return "A::f()"; }
49 };
50 
51 struct ACallback :  A,  Callback
52 {
ACallbackACallback53     ACallback (PyObject* self) : Callback(self) {}
54 
55 
fACallback56     std::string f()
57     {
58         return call_method<std::string>(mSelf, "f");
59     }
60 
default_fACallback61     std::string default_f()
62     {
63         return A::f();
64     }
65 };
66 
67 struct B : A
68 {
fB69     virtual std::string f() { return "B::f()"; }
70 };
71 
72 struct C : A
73 {
fC74     virtual std::string f() { return "C::f()"; }
75 };
76 
77 struct D : A
78 {
fD79     virtual std::string f() { return "D::f()"; }
gD80     std::string g() { return "D::g()"; }
81 };
82 
83 struct DCallback :  D,  Callback
84 {
DCallbackDCallback85     DCallback (PyObject* self) : Callback(self) {}
86 
fDCallback87     std::string f()
88     {
89         return call_method<std::string>(mSelf, "f");
90     }
91 
default_fDCallback92     std::string default_f()
93     {
94         return A::f();
95     }
96 };
97 
98 
getBCppObj()99 A& getBCppObj ()
100 {
101     static B b;
102     return b;
103 }
104 
call_f(A & a)105 std::string call_f(A& a) { return a.f(); }
106 
factory(unsigned choice)107 A* factory(unsigned choice)
108 {
109     switch (choice % 3)
110     {
111     case 0: return new A;
112         break;
113     case 1: return new B;
114         break;
115     default: return new C;
116         break;
117     }
118 }
119 
getCCppObj()120 C& getCCppObj ()
121 {
122     static C c;
123     return c;
124 }
125 
pass_a(A * x)126 A* pass_a(A* x) { return x; }
127 
BOOST_PYTHON_MODULE_INIT(polymorphism_ext)128 BOOST_PYTHON_MODULE_INIT(polymorphism_ext)
129 {
130     class_<A,boost::noncopyable,ACallback>("A")
131         .def("f", &A::f, &ACallback::default_f)
132         ;
133 
134     def("getBCppObj", getBCppObj, return_value_policy<reference_existing_object>());
135 
136     class_<C,bases<A>,boost::noncopyable>("C")
137         .def("f", &C::f)
138         ;
139 
140     class_<D,bases<A>,DCallback,boost::noncopyable>("D")
141         .def("f", &D::f, &DCallback::default_f)
142         .def("g", &D::g)
143         ;
144 
145     def("pass_a", &pass_a,  return_internal_reference<>());
146 
147     def("getCCppObj", getCCppObj, return_value_policy<reference_existing_object>());
148 
149     def("factory", factory, return_value_policy<manage_new_object>());
150 
151     def("call_f", call_f);
152 
153     class_<P,boost::noncopyable,PCallback>("P")
154         .def("f", pure_virtual(&P::f))
155         ;
156 
157     class_<Q, bases<P> >("Q")
158         .def("g", &P::g) // make sure virtual inheritance doesn't interfere
159         ;
160 }
161 
162 //#include "module_tail.cpp"
163