@@ -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