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