Skip to content

Commit 0389aab

Browse files
committed
Nicer syntactic sugar
[SVN r12447]
1 parent 51a66a3 commit 0389aab

5 files changed

Lines changed: 90 additions & 65 deletions

File tree

include/boost/python/class.hpp

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
#ifndef CLASS_DWA200216_HPP
77
# define CLASS_DWA200216_HPP
88

9-
# include <boost/python/module.hpp>
109
# include <boost/python/reference.hpp>
1110
# include <boost/python/object/class.hpp>
1211
# include <boost/python/converter/type_id.hpp>
@@ -84,26 +83,26 @@ template <
8483
, class Bases = mpl::type_list<>::type
8584
, class HolderGenerator = objects::value_holder_generator
8685
>
87-
class class_ : objects::class_base
86+
class class_ : private objects::class_base
8887
{
8988
typedef class_<T,Bases,HolderGenerator> self;
9089
public:
9190

92-
// Construct with the module and automatically derive the class
93-
// name
94-
class_(module&);
91+
// Automatically derive the class name - only works on some
92+
// compilers because type_info::name is sometimes mangled (gcc)
93+
class_();
9594

96-
// Construct with the module and class name. [ Would have used a
97-
// default argument but gcc-2.95.2 choked on typeid(T).name() as a
98-
// default parameter value]
99-
class_(module&, char const* name);
95+
// Construct with the class name. [ Would have used a default
96+
// argument but gcc-2.95.2 choked on typeid(T).name() as a default
97+
// parameter value]
98+
class_(char const* name);
10099

101100

102101
// Wrap a member function or a non-member function which can take
103102
// a T, T cv&, or T cv* as its first parameter, or a callable
104103
// python object.
105104
template <class F>
106-
self& def(F f, char const* name)
105+
self& def(char const* name, F f)
107106
{
108107
// Use function::add_to_namespace to achieve overloading if
109108
// appropriate.
@@ -117,7 +116,7 @@ class class_ : objects::class_base
117116
template <class Args>
118117
self& def_init(Args const& = Args())
119118
{
120-
def(make_constructor<T,Args,HolderGenerator>(), "__init__");
119+
def("__init__", make_constructor<T,Args,HolderGenerator>());
121120
return *this;
122121
}
123122

@@ -128,6 +127,9 @@ class class_ : objects::class_base
128127
return *this;
129128
}
130129

130+
// return the underlying object
131+
ref object() const;
132+
131133
private: // types
132134
typedef objects::class_id class_id;
133135

@@ -160,9 +162,8 @@ class class_ : objects::class_base
160162
// implementations
161163
//
162164
template <class T, class Bases, class HolderGenerator>
163-
inline class_<T, Bases, HolderGenerator>::class_(
164-
module& m)
165-
: class_base(m, typeid(T).name(), id_vector::size, id_vector().ids)
165+
inline class_<T, Bases, HolderGenerator>::class_()
166+
: class_base(typeid(T).name(), id_vector::size, id_vector().ids)
166167
{
167168
// Bring the class converters into existence. This static object
168169
// will survive until the shared library this module lives in is
@@ -171,16 +172,21 @@ inline class_<T, Bases, HolderGenerator>::class_(
171172
}
172173

173174
template <class T, class Bases, class HolderGenerator>
174-
inline class_<T, Bases, HolderGenerator>::class_(
175-
module& m, char const* name)
176-
: class_base(m, name, id_vector::size, id_vector().ids)
175+
inline class_<T, Bases, HolderGenerator>::class_(char const* name)
176+
: class_base(name, id_vector::size, id_vector().ids)
177177
{
178178
// Bring the class converters into existence. This static object
179179
// will survive until the shared library this module lives in is
180180
// unloaded (that doesn't happen until Python terminates).
181181
static objects::class_converters<T,Bases> converters(object());
182182
}
183183

184+
template <class T, class Bases, class HolderGenerator>
185+
inline ref class_<T, Bases, HolderGenerator>::object() const
186+
{
187+
return this->class_base::object();
188+
}
189+
184190
}} // namespace boost::python
185191

186192
#endif // CLASS_DWA200216_HPP

include/boost/python/module.hpp

Lines changed: 52 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515

1616
namespace boost { namespace python {
1717

18+
template <class T, class Bases, class HolderGenerator> class class_;
19+
1820
class BOOST_PYTHON_DECL module_base
1921
{
2022
public:
@@ -23,18 +25,12 @@ class BOOST_PYTHON_DECL module_base
2325
~module_base();
2426

2527
// Add elements to the module
26-
void add(PyObject* x, const char* name);
27-
void add(PyTypeObject* x, const char* name = 0);
28-
void add(ref const& x, const char*name);
29-
30-
// Return true iff a module is currently being built.
31-
static bool initializing();
28+
void setattr(const char* name, PyObject*);
29+
void setattr(const char* name, ref const&);
30+
void add(PyTypeObject* x); // just use the type's name
31+
void add_type(ref);
3232

33-
// Return the name of the module currently being built.
34-
// REQUIRES: initializing() == true
35-
static string name();
36-
37-
// Return a pointer to the Python module object being built
33+
// Return a reference to the Python module object being built
3834
ref module() const;
3935

4036
private:
@@ -48,17 +44,34 @@ class module : public module_base
4844
module(const char* name)
4945
: module_base(name) {}
5046

47+
// Add elements to the module
48+
module& setattr(const char* name, PyObject*);
49+
module& setattr(const char* name, PyTypeObject*);
50+
module& setattr(const char* name, ref const&);
51+
module& add(PyTypeObject* x); // just use the type's name
52+
53+
template <class T, class Bases, class HolderGenerator>
54+
module& add(class_<T,Bases,HolderGenerator> const& c)
55+
{
56+
std::cout << "adding " << typeid(T).name() << " to module" << std::endl << std::flush;
57+
Py_INCREF(c.object());
58+
this->add_type(c.object());
59+
return *this;
60+
}
61+
5162
# if 0
5263
template <class Fn>
53-
void def_raw(Fn fn, const char* name)
64+
void def_raw(char const* name, Fn fn)
5465
{
5566
add(detail::new_raw_arguments_function(fn), name);
5667
}
57-
# endif
68+
# endif
69+
5870
template <class Fn>
59-
void def(Fn fn, const char* name)
71+
module& def(char const* name, Fn fn)
6072
{
61-
this->add(boost::python::make_function(fn), name);
73+
this->setattr(name, boost::python::make_function(fn));
74+
return *this;
6275
}
6376
};
6477

@@ -70,6 +83,30 @@ inline ref module_base::module() const
7083
return m_module;
7184
}
7285

86+
inline module& module::setattr(const char* name, PyObject* x)
87+
{
88+
this->module_base::setattr(name, x);
89+
return *this;
90+
}
91+
92+
inline module& module::setattr(const char* name, PyTypeObject* x)
93+
{
94+
this->module_base::setattr(name, (PyObject*)x);
95+
return *this;
96+
}
97+
98+
inline module& module::setattr(const char* name, ref const& x)
99+
{
100+
this->module_base::setattr(name, x);
101+
return *this;
102+
}
103+
104+
inline module& module::add(PyTypeObject* x)
105+
{
106+
this->module_base::add(x);
107+
return *this;
108+
}
109+
73110
}} // namespace boost::python
74111

75112
#endif // MODULE_DWA20011221_HPP

include/boost/python/object/class.hpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,7 @@ struct BOOST_PYTHON_DECL class_base : noncopyable
3030
{
3131
// constructor
3232
class_base(
33-
module& name_space // Which name space the class will live in
34-
, char const* name // The name of the class
33+
char const* name // The name of the class
3534

3635
, std::size_t num_types // A list of class_ids. The first is the type
3736
, class_id const*const types // this is wrapping. The rest are the types of

src/module.cpp

Lines changed: 11 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -10,53 +10,38 @@
1010

1111
namespace boost { namespace python {
1212

13-
namespace {
14-
ref name_holder;
15-
}
16-
17-
bool module_base::initializing()
18-
{
19-
return name_holder.get() != 0;
20-
}
21-
22-
string module_base::name()
23-
{
24-
// If this fails, you haven't created a module object
25-
assert(initializing());
26-
return string(name_holder);
27-
}
28-
2913
module_base::module_base(const char* name)
3014
: m_module(
3115
Py_InitModule(const_cast<char*>(name), initial_methods)
3216
, ref::increment_count)
3317
{
34-
// If this fails, you've created more than 1 module object in your module
35-
assert(name_holder.get() == 0);
36-
name_holder = ref(PyObject_GetAttrString(
37-
m_module.get() , const_cast<char*>("__name__")));
3818
}
3919

4020
module_base::~module_base()
4121
{
42-
name_holder.reset();
4322
}
4423

45-
void module_base::add(PyObject* x, const char* name)
24+
void module_base::setattr(const char* name, PyObject* x)
4625
{
47-
add(ref(x), name);
26+
setattr(name, ref(x));
4827
}
4928

50-
void module_base::add(ref const& x, const char* name)
29+
void module_base::setattr(char const* name, ref const& x)
5130
{
5231
// Use function::add_to_namespace to achieve overloading if
5332
// appropriate.
5433
objects::function::add_to_namespace(m_module, name, x);
5534
}
5635

57-
void module_base::add(PyTypeObject* x, const char* name /*= 0*/)
36+
void module_base::add(PyTypeObject* x)
37+
{
38+
this->setattr(x->tp_name, (PyObject*)x);
39+
}
40+
41+
void module_base::add_type(ref x)
5842
{
59-
this->add((PyObject*)x, name ? name : x->tp_name);
43+
assert(PyObject_TypeCheck(x.get(), &PyType_Type));
44+
add((PyTypeObject*)x.release());
6045
}
6146

6247
PyMethodDef module_base::initial_methods[] = { { 0, 0, 0, 0 } };

src/object/class.cpp

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
#include <boost/python/detail/map_entry.hpp>
1212
#include <boost/detail/binary_search.hpp>
1313
#include <boost/bind.hpp>
14-
#include <boost/python/detail/wrap_python.hpp>
1514
#include <functional>
1615
#include <vector>
1716

@@ -190,11 +189,11 @@ namespace
190189

191190
std::vector<entry>::const_iterator p
192191
= boost::detail::lower_bound(start, finish, id);
193-
192+
194193
if (p == finish && p->key != id)
195194
{
196195
string report("extension class wrapper for base class ");
197-
(report += id.name()) += "has not been created yet";
196+
(report += id.name()) += " has not been created yet";
198197
PyErr_SetObject(PyExc_RuntimeError, report.get());
199198
throw error_already_set();
200199
}
@@ -212,7 +211,7 @@ namespace
212211
}
213212

214213
class_base::class_base(
215-
module& m, char const* name, std::size_t num_types, class_id const* const types)
214+
char const* name, std::size_t num_types, class_id const* const types)
216215
{
217216
class_registry& r = registry();
218217
assert(num_types >= 1);
@@ -234,7 +233,6 @@ class_base::class_base(
234233

235234
m_object = ref(PyObject_CallObject(class_metatype().get(), args.get()));
236235
r.set(types[0], m_object);
237-
m.add(m_object, name);
238236
}
239237

240238
}}} // namespace boost::python::objects

0 commit comments

Comments
 (0)