Skip to content

Commit 9795a27

Browse files
committed
Even further rationalized conversion registry
[SVN r14458]
1 parent baccdba commit 9795a27

5 files changed

Lines changed: 63 additions & 87 deletions

File tree

include/boost/python/converter/registry.hpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,11 @@ struct registration;
2020
// This namespace acts as a sort of singleton
2121
namespace registry
2222
{
23+
// Get the registration corresponding to the type, creating it if neccessary
2324
BOOST_PYTHON_DECL registration const& lookup(type_info);
25+
26+
// Return a pointer to the corresponding registration, if one exists
27+
BOOST_PYTHON_DECL registration const* query(type_info);
2428

2529
BOOST_PYTHON_DECL void insert(to_python_function_t, type_info);
2630

@@ -41,8 +45,6 @@ namespace registry
4145
, constructor_function
4246
, type_info
4347
);
44-
45-
BOOST_PYTHON_DECL PyTypeObject*& class_object(type_info key);
4648
}
4749

4850
}}} // namespace boost::python::converter

include/boost/python/object/class_object.hpp

Lines changed: 0 additions & 26 deletions
This file was deleted.

include/boost/python/to_python_indirect.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
# include <boost/type_traits/object_traits.hpp>
1010
# include <boost/python/object/pointer_holder.hpp>
11-
# include <boost/python/object/class_object.hpp>
11+
# include <boost/python/converter/registered.hpp>
1212
# include <boost/python/detail/unwind_type.hpp>
1313
# include <boost/python/detail/none.hpp>
1414
# include <boost/shared_ptr.hpp>
@@ -65,7 +65,7 @@ namespace detail
6565
static result_type execute(T* p)
6666
{
6767
BOOST_STATIC_ASSERT(is_class<T>::value);
68-
return python::objects::class_object<T>::reference;
68+
return converter::registered<T>::converters.class_object;
6969
}
7070
};
7171

src/converter/registry.cpp

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,11 @@ namespace // <unnamed>
5050
entry* get(type_info type)
5151
{
5252
# ifdef BOOST_PYTHON_TRACE_REGISTRY
53+
registry_t::iterator p = entries().find(entry(type));
54+
5355
std::cout << "looking up " << type
54-
<< (entries().find(entry(type)) == entries().end() ? ": not found\n" : ": found\n");
56+
<< (p == entries().end() || p->target_type != type
57+
? "...NOT found\n" : "...found\n");
5558
# endif
5659
return const_cast<entry*>(
5760
&*entries().insert(entry(type)).first
@@ -127,14 +130,20 @@ namespace registry
127130
*found = registration;
128131
}
129132

130-
PyTypeObject*& class_object(type_info key)
133+
registration const& lookup(type_info key)
131134
{
132-
return get(key)->class_object;
135+
return *get(key);
133136
}
134137

135-
registration const& lookup(type_info key)
138+
registration const* query(type_info type)
136139
{
137-
return *get(key);
140+
registry_t::iterator p = entries().find(entry(type));
141+
# ifdef BOOST_PYTHON_TRACE_REGISTRY
142+
std::cout << "querying " << type
143+
<< (p == entries().end() || p->target_type != type
144+
? "...NOT found\n" : "...found\n");
145+
# endif
146+
return (p == entries().end() || p->target_type != type) ? 0 : &*p;
138147
}
139148
} // namespace registry
140149

src/object/class.cpp

Lines changed: 43 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -204,37 +204,22 @@ namespace objects
204204

205205
namespace
206206
{
207-
struct class_registry
207+
// Find a registered class object corresponding to id. Return a
208+
// null handle if no such class is registered.
209+
inline type_handle query_class(class_id id)
208210
{
209-
public:
210-
type_handle get(class_id id) const;
211-
type_handle query(class_id id) const;
212-
void set(class_id, type_handle class_object);
213-
private:
214-
typedef python::detail::map_entry<class_id,type_handle> entry;
215-
std::vector<entry> m_impl;
216-
};
217-
218-
class_registry& registry()
219-
{
220-
static class_registry x;
221-
return x;
211+
converter::registration const* p = converter::registry::query(id);
212+
return type_handle(
213+
python::borrowed(
214+
python::allow_null(p ? p->class_object : 0))
215+
);
222216
}
223217

224-
inline type_handle class_registry::query(class_id id) const
218+
// Find a registered class corresponding to id. If not found,
219+
// throw an appropriate exception.
220+
type_handle get_class(class_id id)
225221
{
226-
std::vector<entry>::const_iterator start = m_impl.begin();
227-
std::vector<entry>::const_iterator finish = m_impl.end();
228-
229-
std::vector<entry>::const_iterator p
230-
= boost::detail::lower_bound(start, finish, id);
231-
232-
return (p == finish || p->key != id) ? type_handle() : p->value;
233-
}
234-
235-
inline type_handle class_registry::get(class_id id) const
236-
{
237-
type_handle result(this->query(id));
222+
type_handle result(query_class(id));
238223

239224
if (result.get() == 0)
240225
{
@@ -245,48 +230,54 @@ namespace objects
245230
}
246231
return result;
247232
}
248-
249-
inline void class_registry::set(class_id id, type_handle object)
250-
{
251-
std::vector<entry>::iterator start = m_impl.begin();
252-
std::vector<entry>::iterator finish = m_impl.end();
253-
m_impl.insert(
254-
boost::detail::lower_bound(start, finish, id)
255-
, entry(id, object));
256-
converter::registry::class_object(id) = (PyTypeObject*)object.get();
257-
}
258233
}
259234

235+
// class_base constructor
236+
//
237+
// name - the name of the new Python class
238+
//
239+
// num_types - one more than the number of declared bases
240+
//
241+
// types - array of python::type_info, the first item
242+
// corresponding to the class being created, and the
243+
// rest corresponding to its declared bases.
244+
//
260245
class_base::class_base(
261246
char const* name, std::size_t num_types, class_id const* const types)
262247
{
263-
class_registry& r = registry();
264248
assert(num_types >= 1);
265249

266-
handle<> bases(
267-
PyTuple_New(std::max(num_types - 1, static_cast<std::size_t>(1)))
268-
);
269-
270-
if (num_types > 1)
271-
{
272-
for (std::size_t i = 1; i < num_types; ++i)
273-
PyTuple_SET_ITEM(bases.get(), i - 1, upcast<PyObject>(r.get(types[i]).release()));
274-
}
275-
else
250+
// Build a tuple of the base Python type objects. If no bases
251+
// were declared, we'll use our class_type() as the single base
252+
// class.
253+
std::size_t const num_bases = std::max(num_types - 1, static_cast<std::size_t>(1));
254+
handle<> bases(PyTuple_New(num_bases));
255+
256+
for (std::size_t i = 1; i <= num_bases; ++i)
276257
{
277-
PyTuple_SET_ITEM(bases.get(), 0, upcast<PyObject>(class_type().release()));
258+
type_handle c = (i >= num_types) ? class_type() : get_class(types[i]);
259+
// PyTuple_SET_ITEM steals this reference
260+
PyTuple_SET_ITEM(bases.get(), i - 1, upcast<PyObject>(c.release()));
278261
}
279-
262+
263+
// Build the (name, bases, dict) tuple for creating the new class
280264
handle<> args(PyTuple_New(3));
281265
PyTuple_SET_ITEM(args.get(), 0, incref(python::object(name).ptr()));
282266
PyTuple_SET_ITEM(args.get(), 1, bases.release());
283267
handle<> d(PyDict_New());
284268
PyTuple_SET_ITEM(args.get(), 2, d.release());
285269

270+
// Call the class metatype to create a new class
286271
PyObject* c = PyObject_CallObject(upcast<PyObject>(class_metatype().get()), args.get());
287272
assert(PyType_IsSubtype(c->ob_type, &PyType_Type));
288273
m_object = type_handle((PyTypeObject*)c);
289-
r.set(types[0], m_object);
274+
275+
// Insert the new class object in the registry
276+
converter::registration& converters = const_cast<converter::registration&>(
277+
converter::registry::lookup(types[0]));
278+
279+
// Class object is leaked, for now
280+
converters.class_object = (PyTypeObject*)incref(m_object.get());
290281
}
291282

292283
extern "C"
@@ -315,7 +306,7 @@ namespace objects
315306

316307
BOOST_PYTHON_DECL type_handle registered_class_object(class_id id)
317308
{
318-
return registry().query(id);
309+
return objects::query_class(id);
319310
}
320311
} // namespace objects
321312

0 commit comments

Comments
 (0)