1 // Copyright David Abrahams 2001.
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 
6 
7 #include <boost/python/def.hpp>
8 #include <boost/python/module.hpp>
9 #include <boost/python/class.hpp>
10 #include <boost/python/lvalue_from_pytype.hpp>
11 #include <boost/python/copy_const_reference.hpp>
12 #include <boost/python/return_value_policy.hpp>
13 #include <boost/python/to_python_converter.hpp>
14 #include <boost/python/errors.hpp>
15 #include <boost/python/manage_new_object.hpp>
16 #include <boost/python/converter/pytype_function.hpp>
17 #include <string.h>
18 #include "simple_type.hpp"
19 #include "complicated.hpp"
20 
21 // Declare some straightforward extension types
22 extern "C" void
dealloc(PyObject * self)23 dealloc(PyObject* self)
24 {
25     PyObject_Del(self);
26 }
27 
28 // Noddy is a type we got from one of the Python sample files
29 struct NoddyObject : PyObject
30 {
31     int x;
32 };
33 
34 PyTypeObject NoddyType = {
35     PyVarObject_HEAD_INIT(NULL, 0)
36     const_cast<char*>("Noddy"),
37     sizeof(NoddyObject),
38     0,
39     dealloc,    /* tp_dealloc */
40     0,          /* tp_print */
41     0,          /* tp_getattr */
42     0,          /* tp_setattr */
43     0,          /* tp_compare */
44     0,          /* tp_repr */
45     0,          /* tp_as_number */
46     0,          /* tp_as_sequence */
47     0,          /* tp_as_mapping */
48     0,          /* tp_hash */
49     0,          /* tp_call */
50     0,          /* tp_str */
51     0,          /* tp_getattro */
52     0,          /* tp_setattro */
53     0,          /* tp_as_buffer */
54     0,          /* tp_flags */
55     0,          /* tp_doc */
56     0,          /* tp_traverse */
57     0,          /* tp_clear */
58     0,          /* tp_richcompare */
59     0,          /* tp_weaklistoffset */
60     0,          /* tp_iter */
61     0,          /* tp_iternext */
62     0,          /* tp_methods */
63     0,          /* tp_members */
64     0,          /* tp_getset */
65     0,          /* tp_base */
66     0,          /* tp_dict */
67     0,          /* tp_descr_get */
68     0,          /* tp_descr_set */
69     0,          /* tp_dictoffset */
70     0,          /* tp_init */
71     0,          /* tp_alloc */
72     0,          /* tp_new */
73     0,          /* tp_free */
74     0,          /* tp_is_gc */
75     0,          /* tp_bases */
76     0,          /* tp_mro */
77     0,          /* tp_cache */
78     0,          /* tp_subclasses */
79     0,          /* tp_weaklist */
80 #if PYTHON_API_VERSION >= 1012
81     0           /* tp_del */
82 #endif
83 };
84 
85 // Create a Noddy containing 42
new_noddy()86 PyObject* new_noddy()
87 {
88     NoddyObject* noddy = PyObject_New(NoddyObject, &NoddyType);
89     noddy->x = 42;
90     return (PyObject*)noddy;
91 }
92 
93 // Simple is a wrapper around a struct simple, which just contains a char*
94 struct SimpleObject
95 {
96     PyObject_HEAD
97     simple x;
98 };
99 
100 struct extract_simple_object
101 {
executeextract_simple_object102     static simple& execute(SimpleObject& o) { return o.x; }
103 };
104 
105 PyTypeObject SimpleType = {
106     PyVarObject_HEAD_INIT(NULL, 0)
107     const_cast<char*>("Simple"),
108     sizeof(SimpleObject),
109     0,
110     dealloc,    /* tp_dealloc */
111     0,          /* tp_print */
112     0,          /* tp_getattr */
113     0,          /* tp_setattr */
114     0,          /* tp_compare */
115     0,          /* tp_repr */
116     0,          /* tp_as_number */
117     0,          /* tp_as_sequence */
118     0,          /* tp_as_mapping */
119     0,          /* tp_hash */
120     0,          /* tp_call */
121     0,          /* tp_str */
122     0,          /* tp_getattro */
123     0,          /* tp_setattro */
124     0,          /* tp_as_buffer */
125     0,          /* tp_flags */
126     0,          /* tp_doc */
127     0,          /* tp_traverse */
128     0,          /* tp_clear */
129     0,          /* tp_richcompare */
130     0,          /* tp_weaklistoffset */
131     0,          /* tp_iter */
132     0,          /* tp_iternext */
133     0,          /* tp_methods */
134     0,          /* tp_members */
135     0,          /* tp_getset */
136     0,          /* tp_base */
137     0,          /* tp_dict */
138     0,          /* tp_descr_get */
139     0,          /* tp_descr_set */
140     0,          /* tp_dictoffset */
141     0,          /* tp_init */
142     0,          /* tp_alloc */
143     0,          /* tp_new */
144     0,          /* tp_free */
145     0,          /* tp_is_gc */
146     0,          /* tp_bases */
147     0,          /* tp_mro */
148     0,          /* tp_cache */
149     0,          /* tp_subclasses */
150     0,          /* tp_weaklist */
151 #if PYTHON_API_VERSION >= 1012
152     0           /* tp_del */
153 #endif
154 };
155 
156 // Create a Simple containing "hello, world"
new_simple()157 PyObject* new_simple()
158 {
159     SimpleObject* simple = PyObject_New(SimpleObject, &SimpleType);
160     simple->x.s = const_cast<char*>("hello, world");
161     return (PyObject*)simple;
162 }
163 
164 //
165 // Declare some wrappers/unwrappers to test the low-level conversion
166 // mechanism.
167 //
168 using boost::python::to_python_converter;
169 
170 // Wrap a simple by copying it into a Simple
171 struct simple_to_python
172     : to_python_converter<simple, simple_to_python, true>
173     //, boost::python::converter::wrap_pytype<&SimpleType>
174 {
convertsimple_to_python175     static PyObject* convert(simple const& x)
176     {
177         SimpleObject* p = PyObject_New(SimpleObject, &SimpleType);
178         p->x = x;
179         return (PyObject*)p;
180     }
get_pytypesimple_to_python181     static PyTypeObject const *get_pytype(){return &SimpleType; }
182 };
183 
184 struct int_from_noddy
185 {
executeint_from_noddy186     static int& execute(NoddyObject& p)
187     {
188         return p.x;
189     }
190 };
191 
192 //
193 // Some C++ functions to expose to Python
194 //
195 
196 // Returns the length of s's held string
f(simple const & s)197 int f(simple const& s)
198 {
199     return strlen(s.s);
200 }
201 
f_mutable_ref(simple & s)202 int f_mutable_ref(simple& s)
203 {
204     return strlen(s.s);
205 }
206 
f_mutable_ptr(simple * s)207 int f_mutable_ptr(simple* s)
208 {
209     return strlen(s->s);
210 }
211 
f_const_ptr(simple const * s)212 int f_const_ptr(simple const* s)
213 {
214     return strlen(s->s);
215 }
216 
f2(SimpleObject const & s)217 int f2(SimpleObject const& s)
218 {
219     return strlen(s.x.s);
220 }
221 
222 // A trivial passthru function for simple objects
g(simple const & x)223 simple const& g(simple const& x)
224 {
225     return x;
226 }
227 
228 struct A
229 {
AA230     A() : x(0) {}
~AA231     virtual ~A() {}
nameA232     char const* name() { return "A"; }
233     int x;
234 };
235 
236 struct B : A
237 {
BB238     B() : x(1) {}
nameB239     static char const* name(B*) { return "B"; }
240     int x;
241 };
242 
243 struct C : A
244 {
CC245     C() : x(2) {}
nameC246     char const* name() { return "C"; }
~CC247     virtual ~C() {}
248     int x;
249 };
250 
251 struct D : B, C
252 {
DD253     D() : x(3) {}
nameD254     char const* name() { return "D"; }
255     int x;
256 };
257 
take_a(A const & a)258 A take_a(A const& a) { return a; }
take_b(B & b)259 B take_b(B& b) { return b; }
take_c(C * c)260 C take_c(C* c) { return *c; }
take_d(D * const & d)261 D take_d(D* const& d) { return *d; }
262 
take_d_shared_ptr(boost::shared_ptr<D> d)263 D take_d_shared_ptr(boost::shared_ptr<D> d) { return *d; }
264 
d_factory()265 boost::shared_ptr<A> d_factory() { return boost::shared_ptr<B>(new D); }
266 
267 struct Unregistered {};
make_unregistered(int)268 Unregistered make_unregistered(int) { return Unregistered(); }
269 
make_unregistered2(int)270 Unregistered* make_unregistered2(int) { return new Unregistered; }
271 
BOOST_PYTHON_MODULE(m1)272 BOOST_PYTHON_MODULE(m1)
273 {
274     using namespace boost::python;
275     using boost::shared_ptr;
276 
277     simple_to_python();
278 
279     lvalue_from_pytype<int_from_noddy,&NoddyType>();
280 
281     lvalue_from_pytype<
282 #if !defined(BOOST_MSVC) || BOOST_MSVC > 1300 // doesn't support non-type member pointer parameters
283         extract_member<SimpleObject, simple, &SimpleObject::x>
284 #else
285         extract_simple_object
286 #endif
287         , &SimpleType
288         >();
289 
290     lvalue_from_pytype<extract_identity<SimpleObject>,&SimpleType>();
291 
292     def("new_noddy", new_noddy);
293     def("new_simple", new_simple);
294 
295     def("make_unregistered", make_unregistered);
296     def("make_unregistered2", make_unregistered2, return_value_policy<manage_new_object>());
297 
298       // Expose f() in all its variations
299     def("f", f);
300     def("f_mutable_ref", f_mutable_ref);
301     def("f_mutable_ptr", f_mutable_ptr);
302     def("f_const_ptr", f_const_ptr);
303 
304     def("f2", f2);
305 
306       // Expose g()
307     def("g", g , return_value_policy<copy_const_reference>()
308         );
309 
310     def("take_a", take_a);
311     def("take_b", take_b);
312     def("take_c", take_c);
313     def("take_d", take_d);
314 
315 
316     def("take_d_shared_ptr", take_d_shared_ptr);
317     def("d_factory", d_factory);
318 
319     class_<A, shared_ptr<A> >("A")
320         .def("name", &A::name)
321         ;
322 
323     // sequence points don't ensure that "A" is constructed before "B"
324     // or "C" below if we make them part of the same chain
325     class_<B,bases<A> >("B")
326         .def("name", &B::name)
327         ;
328 
329     class_<C,bases<A> >("C")
330         .def("name", &C::name)
331         ;
332 
333     class_<D, bases<B,C> >("D")
334         .def("name", &D::name)
335         ;
336 
337     class_<complicated>("complicated",
338                         init<simple const&,int>())
339         .def(init<simple const&>())
340         .def("get_n", &complicated::get_n)
341         ;
342 }
343 
344 #include "module_tail.cpp"
345