Skip to content

Commit 586e617

Browse files
committed
commented
[SVN r12209]
1 parent 1201761 commit 586e617

File tree

3 files changed

+90
-16
lines changed

3 files changed

+90
-16
lines changed

test/m1.cpp

Lines changed: 58 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
// to its suitability for any purpose.
66

77
// Seems to be neccessary to suppress an ICE with MSVC
8-
#include "boost/mpl/comparison/less.hpp"
8+
#include <boost/mpl/comparison/less.hpp>
99

1010
#include "simple_type.hpp"
1111
#include "complicated.hpp"
@@ -21,12 +21,14 @@
2121
#include <boost/mpl/type_list.hpp>
2222
#include <string.h>
2323

24+
// Declare some straightforward extension types
2425
extern "C" void
2526
dealloc(PyObject* self)
2627
{
2728
PyObject_Del(self);
2829
}
2930

31+
// Noddy is a type we got from one of the Python sample files
3032
struct NoddyObject : PyObject
3133
{
3234
int x;
@@ -50,6 +52,22 @@ PyTypeObject NoddyType = {
5052
0, /*tp_hash */
5153
};
5254

55+
// Create a Noddy containing 42
56+
extern "C" PyObject*
57+
new_noddy(PyObject* self, PyObject* args)
58+
{
59+
NoddyObject* noddy;
60+
61+
if (!PyArg_ParseTuple(args,":new_noddy"))
62+
return NULL;
63+
64+
noddy = PyObject_New(NoddyObject, &NoddyType);
65+
noddy->x = 42;
66+
67+
return (PyObject*)noddy;
68+
}
69+
70+
// Simple is a wrapper around a struct simple, which just contains a char*
5371
struct SimpleObject : PyObject
5472
{
5573
simple x;
@@ -73,20 +91,7 @@ PyTypeObject SimpleType = {
7391
0, /*tp_hash */
7492
};
7593

76-
extern "C" PyObject*
77-
new_noddy(PyObject* self, PyObject* args)
78-
{
79-
NoddyObject* noddy;
80-
81-
if (!PyArg_ParseTuple(args,":new_noddy"))
82-
return NULL;
83-
84-
noddy = PyObject_New(NoddyObject, &NoddyType);
85-
noddy->x = 42;
86-
87-
return (PyObject*)noddy;
88-
}
89-
94+
// Create a Simple containing "hello, world"
9095
extern "C" PyObject*
9196
new_simple(PyObject* self, PyObject* args)
9297
{
@@ -101,12 +106,21 @@ new_simple(PyObject* self, PyObject* args)
101106
return (PyObject*)simple;
102107
}
103108

109+
// Initial method table for the module
104110
static PyMethodDef methods[] = {
105111
{ "new_noddy", new_noddy, METH_VARARGS },
106112
{ "new_simple", new_simple, METH_VARARGS },
107113
{0, 0, 0, 0}
108114
};
109115

116+
//
117+
// Declare some wrappers/unwrappers to test the low-level conversion
118+
// mechanism. See boost/python/converter/source.hpp,target.hpp for a
119+
// description of how the type parameters to wrapper<> and unwrapper<>
120+
// are selected.
121+
//
122+
123+
// Wrap an int by converting it to a Python Int
110124
struct int_wrapper
111125
: boost::python::converter::wrapper<int const&>
112126
{
@@ -116,6 +130,7 @@ struct int_wrapper
116130
}
117131
};
118132

133+
// Wrap a simple by converting it to a Simple
119134
struct simple_wrapper
120135
: boost::python::converter::wrapper<simple const&>
121136
{
@@ -127,6 +142,10 @@ struct simple_wrapper
127142
}
128143
};
129144

145+
// wrap a mutable reference to a simple by converting it to a
146+
// Simple. Normally we wouldn't do it this way, since modifications to
147+
// the result clearly don't change the original object, but here we're
148+
// just proving that the mechanism works.
130149
struct simple_ref_wrapper
131150
: boost::python::converter::wrapper<simple&>
132151
{
@@ -138,6 +157,9 @@ struct simple_ref_wrapper
138157
}
139158
};
140159

160+
// extract an int from a Python Int by converting it to an int. Since
161+
// int is a scalar type, we convert by-value. Since Python Ints are
162+
// immutable, there's no non-const reference converter.
141163
struct native_int_unwrapper
142164
: boost::python::converter::unwrapper<int>
143165
{
@@ -152,6 +174,7 @@ struct native_int_unwrapper
152174
}
153175
};
154176

177+
// Extract an int from a Noddy
155178
struct noddy_int_unwrapper
156179
: boost::python::converter::unwrapper<int>
157180
{
@@ -166,6 +189,7 @@ struct noddy_int_unwrapper
166189
}
167190
};
168191

192+
// Extract a mutable reference to an int from a Noddy.
169193
struct noddy_int_ref_unwrapper
170194
: boost::python::converter::unwrapper<int&>
171195
{
@@ -180,6 +204,7 @@ struct noddy_int_ref_unwrapper
180204
}
181205
};
182206

207+
// Extract a mutable reference to a simple from a Simple
183208
struct simple_ref_unwrapper
184209
: boost::python::converter::unwrapper<simple&>
185210
{
@@ -194,6 +219,7 @@ struct simple_ref_unwrapper
194219
}
195220
};
196221

222+
// Extract a const reference to a simple from a Simple
197223
struct simple_const_ref_unwrapper
198224
: boost::python::converter::unwrapper<simple const&>
199225
{
@@ -208,11 +234,17 @@ struct simple_const_ref_unwrapper
208234
}
209235
};
210236

237+
//
238+
// Some C++ functions to expose to Python
239+
//
240+
241+
// Returns the length of s's held string
211242
int f(simple const& s)
212243
{
213244
return strlen(s.s);
214245
}
215246

247+
// A trivial passthru function for simple objects
216248
simple const& g(simple const& x)
217249
{
218250
return x;
@@ -222,6 +254,7 @@ BOOST_PYTHON_MODULE_INIT(m1)
222254
{
223255
PyObject* m1 = Py_InitModule(const_cast<char*>("m1"), methods);
224256

257+
// Create the converters; they are self-registering/unregistering.
225258
static int_wrapper wrap_int;
226259
static simple_wrapper wrap_simple;
227260
static native_int_unwrapper unwrap_int1;
@@ -233,32 +266,41 @@ BOOST_PYTHON_MODULE_INIT(m1)
233266
// These compilers will need additional converters
234267
static simple_ref_wrapper wrap_simple_ref;
235268
#endif
269+
270+
// This unwrapper extracts pointers and references to the "complicated" class.
236271
static boost::python::converter::class_unwrapper<complicated> unwrap_complicated;
237272

238273
PyObject* d = PyModule_GetDict(m1);
239274
if (d == NULL)
240275
return;
241276

277+
// Insert the extension metaclass object
242278
if (PyDict_SetItemString(
243279
d, "xclass", (PyObject *)boost::python::object::class_metatype()) < 0)
244280
return;
245281

282+
// Insert the base class for all extension classes
246283
if (PyDict_SetItemString(
247284
d, "xinst", (PyObject *)boost::python::object::class_type()) < 0)
248285
return;
249286

287+
// Expose f()
250288
if (PyDict_SetItemString(
251289
d, "f", boost::python::make_function(f)) < 0)
252290
return;
253291

292+
// Expose g()
254293
if (PyDict_SetItemString(
255294
d, "g", boost::python::make_function(g)) < 0)
256295
return;
257296

297+
// Expose complicated's get_n() member function. See newtest.py
298+
// for how it's used to build an extension class.
258299
if (PyDict_SetItemString(
259300
d, "get_n", boost::python::make_function(&complicated::get_n)) < 0)
260301
return;
261302

303+
// Expose complicated::complicated(simple const&, int) as init1
262304
if (PyDict_SetItemString(
263305
d, "init1"
264306
, boost::python::make_constructor<
@@ -268,6 +310,7 @@ BOOST_PYTHON_MODULE_INIT(m1)
268310
) < 0)
269311
return;
270312

313+
// Expose complicated::complicated(simple const&) as init2
271314
if (PyDict_SetItemString(
272315
d, "init2"
273316
, boost::python::make_constructor<

test/m2.cpp

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,24 @@
44
// "as is" without express or implied warranty, and with no claim as
55
// to its suitability for any purpose.
66

7+
// This module exercises the converters exposed in m1 at a low level
8+
// by exposing raw Python extension functions that use wrap<> and
9+
// unwrap<> objects.
10+
11+
// Seems to be neccessary to suppress an ICE with MSVC
12+
#include <boost/mpl/comparison/less.hpp>
13+
714
#include <boost/python/convert.hpp>
815
#include <boost/python/module.hpp>
916
#include "simple_type.hpp"
1017

1118
using boost::python::wrap;
1219
using boost::python::unwrap;
1320

14-
extern "C" {
21+
extern "C"
22+
{
23+
// Get a simple (by value) from the argument, and return the
24+
// string it holds.
1525
PyObject*
1626
unwrap_simple(PyObject* self, PyObject* args)
1727
{
@@ -28,6 +38,8 @@ extern "C" {
2838
return PyString_FromString(x.s);
2939
};
3040

41+
// Likewise, but demands that its possible to get a non-const
42+
// reference to the simple.
3143
PyObject*
3244
unwrap_simple_ref(PyObject* self, PyObject* args)
3345
{
@@ -44,6 +56,7 @@ extern "C" {
4456
return PyString_FromString(x.s);
4557
};
4658

59+
// Likewise, with a const reference to the simple object.
4760
PyObject*
4861
unwrap_simple_const_ref(PyObject* self, PyObject* args)
4962
{
@@ -60,6 +73,8 @@ extern "C" {
6073
return PyString_FromString(x.s);
6174
};
6275

76+
// Get an int (by value) from the argument, and convert it to a
77+
// Python Int.
6378
PyObject*
6479
unwrap_int(PyObject* self, PyObject* args)
6580
{
@@ -76,6 +91,7 @@ extern "C" {
7691
return PyInt_FromLong(x);
7792
};
7893

94+
// Get a non-const reference to an int from the argument
7995
PyObject*
8096
unwrap_int_ref(PyObject* self, PyObject* args)
8197
{
@@ -92,6 +108,7 @@ extern "C" {
92108
return PyInt_FromLong(x);
93109
};
94110

111+
// Get a const reference to an int from the argument.
95112
PyObject*
96113
unwrap_int_const_ref(PyObject* self, PyObject* args)
97114
{
@@ -110,8 +127,12 @@ extern "C" {
110127

111128
// -------------------
112129
}
130+
131+
// MSVC6 bug workaround
113132
template <class T> struct xxxx;
114133

134+
// rewrap<T> extracts a T from the argument, then converts the T back
135+
// to a PyObject* and returns it.
115136
template <class T>
116137
PyObject*
117138
rewrap(PyObject* self, PyObject* args, xxxx<T>* = 0)
@@ -134,6 +155,10 @@ rewrap(PyObject* self, PyObject* args, xxxx<T>* = 0)
134155

135156
extern "C"
136157
{
158+
//
159+
// Use rewrap<T> to test simple, simple&, simple const&, int,
160+
// int&, int const&
161+
//
137162
PyObject*
138163
wrap_simple(PyObject* self, PyObject* args)
139164
{

test/newtest.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,11 +59,17 @@
5959
>>> f(g(s))
6060
12
6161
62+
Create an extension class which wraps "complicated" (init1 and get_n)
63+
are a complicated constructor and member function, respectively.
64+
6265
>>> C = xclass('C', (xinst,), {'__init__': init1, 'get_n': get_n})
6366
>>> c = C(s, 99)
6467
>>> c.get_n()
6568
99
6669
70+
Create another extension class which wraps "complicated" (init2 is a
71+
different constructor -- no overloading yet).
72+
6773
>>> D = xclass('D', (xinst,), {'__init__': init2, 'get_n': get_n})
6874
>>> d = D(s)
6975
>>> d.get_n()

0 commit comments

Comments
 (0)