From b8aaf7d7b1c32045abe229f6e9e6b45eb51febc7 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Thu, 11 Jul 2002 21:04:33 +0000 Subject: [PATCH] Rationalized conversion registry Better error reporting [SVN r14412] --- .../python/converter/arg_from_python.hpp | 12 +-- .../converter/callback_from_python_base.hpp | 12 ++- .../python/converter/find_from_python.hpp | 16 ++-- ..._from_python_chain.hpp => from_python.hpp} | 39 ++++++---- include/boost/python/converter/implicit.hpp | 12 +-- .../converter/lvalue_from_python_chain.hpp | 72 ------------------ .../python/converter/pointee_from_python.hpp | 63 ++++++++++++++++ .../boost/python/converter/registrations.hpp | 27 ++++++- include/boost/python/converter/registry.hpp | 6 +- .../python/converter/return_from_python.hpp | 28 ++----- src/converter/callback.cpp | 47 +++++------- src/converter/from_python.cpp | 67 +++++++++++------ src/converter/registry.cpp | 73 +++++++++---------- 13 files changed, 241 insertions(+), 233 deletions(-) rename include/boost/python/converter/{rvalue_from_python_chain.hpp => from_python.hpp} (52%) delete mode 100644 include/boost/python/converter/lvalue_from_python_chain.hpp create mode 100644 include/boost/python/converter/pointee_from_python.hpp diff --git a/include/boost/python/converter/arg_from_python.hpp b/include/boost/python/converter/arg_from_python.hpp index cf9e15ae..efd60652 100755 --- a/include/boost/python/converter/arg_from_python.hpp +++ b/include/boost/python/converter/arg_from_python.hpp @@ -14,8 +14,8 @@ # include # include # include -# include -# include +# include +# include # include # include # include @@ -229,7 +229,7 @@ inline pointer_cref_arg_from_python::pointer_cref_arg_from_python(PyObject* p // a U object. python::detail::write_void_ptr_reference( m_result.bytes - , p == Py_None ? p : find(p, lvalue_from_python_chain::value) + , p == Py_None ? p : converter::get_lvalue_from_python(p, pointee_from_python::converters) , (T(*)())0); } @@ -252,7 +252,7 @@ inline T pointer_cref_arg_from_python::operator()(PyObject* p) const template inline pointer_arg_from_python::pointer_arg_from_python(PyObject* p) : arg_lvalue_from_python_base( - p == Py_None ? p : find(p, lvalue_from_python_chain::value)) + p == Py_None ? p : converter::get_lvalue_from_python(p, pointee_from_python::converters)) { } @@ -266,7 +266,7 @@ inline T pointer_arg_from_python::operator()(PyObject* p) const // template inline reference_arg_from_python::reference_arg_from_python(PyObject* p) - : arg_lvalue_from_python_base(find(p,lvalue_from_python_chain::value)) + : arg_lvalue_from_python_base(converter::get_lvalue_from_python(p,from_python::converters)) { } @@ -281,7 +281,7 @@ inline T reference_arg_from_python::operator()(PyObject*) const // template inline arg_rvalue_from_python::arg_rvalue_from_python(PyObject* obj) - : m_data(find(obj, rvalue_from_python_chain::value)) + : m_data(converter::rvalue_from_python_stage1(obj, from_python::converters)) { } diff --git a/include/boost/python/converter/callback_from_python_base.hpp b/include/boost/python/converter/callback_from_python_base.hpp index 462857af..63d078af 100644 --- a/include/boost/python/converter/callback_from_python_base.hpp +++ b/include/boost/python/converter/callback_from_python_base.hpp @@ -8,16 +8,14 @@ namespace boost { namespace python { namespace converter { +struct rvalue_from_python_stage1_data; +struct from_python_registration; + namespace detail { - - // Throw an exception - BOOST_PYTHON_DECL void throw_if_not_registered(rvalue_from_python_stage1_data const&); BOOST_PYTHON_DECL void* convert_rvalue(PyObject*, rvalue_from_python_stage1_data&, void* storage); - - BOOST_PYTHON_DECL void throw_if_not_registered(lvalue_from_python_registration*const&); - BOOST_PYTHON_DECL void* callback_convert_reference(PyObject*, lvalue_from_python_registration*const&); - BOOST_PYTHON_DECL void* callback_convert_pointer(PyObject*, lvalue_from_python_registration*const&); + BOOST_PYTHON_DECL void* callback_convert_reference(PyObject*, from_python_registration const&); + BOOST_PYTHON_DECL void* callback_convert_pointer(PyObject*, from_python_registration const&); BOOST_PYTHON_DECL void absorb_result(PyObject*); } diff --git a/include/boost/python/converter/find_from_python.hpp b/include/boost/python/converter/find_from_python.hpp index 659848ce..8a3421ee 100644 --- a/include/boost/python/converter/find_from_python.hpp +++ b/include/boost/python/converter/find_from_python.hpp @@ -12,17 +12,17 @@ namespace boost { namespace python { namespace converter { -struct lvalue_from_python_registration; -struct rvalue_from_python_registration; +struct from_python_registration; +struct rvalue_from_python_chain; -BOOST_PYTHON_DECL void* find( - PyObject* source, lvalue_from_python_registration const*); +BOOST_PYTHON_DECL void* get_lvalue_from_python( + PyObject* source, from_python_registration const&); -BOOST_PYTHON_DECL rvalue_from_python_stage1_data find( - PyObject* source, rvalue_from_python_registration const*); +BOOST_PYTHON_DECL rvalue_from_python_stage1_data rvalue_from_python_stage1( + PyObject* source, from_python_registration const&); -BOOST_PYTHON_DECL rvalue_from_python_registration const* find_chain( - PyObject* source, rvalue_from_python_registration const*); +BOOST_PYTHON_DECL rvalue_from_python_chain const* implicit_conversion_chain( + PyObject* source, from_python_registration const&); }}} // namespace boost::python::converter diff --git a/include/boost/python/converter/rvalue_from_python_chain.hpp b/include/boost/python/converter/from_python.hpp similarity index 52% rename from include/boost/python/converter/rvalue_from_python_chain.hpp rename to include/boost/python/converter/from_python.hpp index 4576e7fc..e712c7fa 100644 --- a/include/boost/python/converter/rvalue_from_python_chain.hpp +++ b/include/boost/python/converter/from_python.hpp @@ -3,8 +3,8 @@ // copyright notice appears in all copies. This software is provided // "as is" without express or implied warranty, and with no claim as // to its suitability for any purpose. -#ifndef RVALUE_FROM_PYTHON_CHAIN_DWA200237_HPP -# define RVALUE_FROM_PYTHON_CHAIN_DWA200237_HPP +#ifndef FROM_PYTHON_DWA2002710_HPP +# define FROM_PYTHON_DWA2002710_HPP # include # include # include @@ -12,29 +12,42 @@ namespace boost { namespace python { namespace converter { +struct from_python_registration; + namespace detail { template - struct rvalue_from_python_chain_impl + struct from_python_base { - static rvalue_from_python_registration*const& value; + static from_python_registration const& converters; }; - - template - rvalue_from_python_registration*const& rvalue_from_python_chain_impl::value - = registry::rvalue_converters(type_id()); } template -struct rvalue_from_python_chain - : detail::rvalue_from_python_chain_impl< +struct from_python + : detail::from_python_base< typename add_reference< - typename add_cv::type + typename add_cv::type >::type - > + > { }; +# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +// collapses a few more types to the same static instance +template +struct from_python : from_python {}; +# endif + +// +// implementations +// +namespace detail +{ + template + from_python_registration const& from_python_base::converters + = registry::from_python_converters(type_id()); +} }}} // namespace boost::python::converter -#endif // RVALUE_FROM_PYTHON_CHAIN_DWA200237_HPP +#endif // FROM_PYTHON_DWA2002710_HPP diff --git a/include/boost/python/converter/implicit.hpp b/include/boost/python/converter/implicit.hpp index 48d680aa..e5675e5d 100644 --- a/include/boost/python/converter/implicit.hpp +++ b/include/boost/python/converter/implicit.hpp @@ -16,16 +16,18 @@ struct implicit static void* convertible(PyObject* obj) { // Find a converter registration which can produce a Source - // instance from obj - return const_cast( - find_chain(obj, rvalue_from_python_chain::value)); + // instance from obj. The user has told us that Source can be + // converted to Target, and instantiating construct() below, + // ensures that at compile-time. + return const_cast( + converter::implicit_conversion_chain(obj, from_python::converters)); } static void construct(PyObject* obj, rvalue_from_python_stage1_data* data) { // This is the registration we got from the convertible step - rvalue_from_python_registration const* registration - = static_cast(data->convertible); + rvalue_from_python_chain const* registration + = static_cast(data->convertible); // Call the convertible function again rvalue_from_python_data intermediate_data(registration->convertible(obj)); diff --git a/include/boost/python/converter/lvalue_from_python_chain.hpp b/include/boost/python/converter/lvalue_from_python_chain.hpp deleted file mode 100644 index 0695025c..00000000 --- a/include/boost/python/converter/lvalue_from_python_chain.hpp +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright David Abrahams 2002. Permission to copy, use, -// modify, sell and distribute this software is granted provided this -// copyright notice appears in all copies. This software is provided -// "as is" without express or implied warranty, and with no claim as -// to its suitability for any purpose. -#ifndef LVALUE_FROM_PYTHON_CHAIN_DWA200237_HPP -# define LVALUE_FROM_PYTHON_CHAIN_DWA200237_HPP - -# include -# include -# include -# include -# include - -namespace boost { namespace python { namespace converter { - -// Given T == U*cv&, T == U*, or T == U&, lvalue_from_python_chain -// declares a "templated global reference" to the lvalue from_python -// converter chain for U. The optional bool second argument is_return, -// when true, removes the usual special treatment which causes the -// converter for U* to bve used when T == U*cv& -namespace detail -{ - template - struct ptr_or_ptr_ref_lvalue_from_python_chain - { - static lvalue_from_python_registration*const& value; - }; - - template - lvalue_from_python_registration*const& - ptr_or_ptr_ref_lvalue_from_python_chain::value - = registry::lvalue_converters(pointer_type_id()); - - template - struct ref_lvalue_from_python_chain - { - static lvalue_from_python_registration*const& value; - }; - - template - lvalue_from_python_registration*const& - ref_lvalue_from_python_chain::value - = registry::lvalue_converters(type_id()); - - template - struct select_lvalue_from_python_chain - { - BOOST_STATIC_CONSTANT( - bool, ptr - = !is_return && boost::python::detail::is_reference_to_pointer::value - || is_pointer::value); - - typedef typename add_reference::type>::type normalized; - - typedef typename mpl::select_type< - ptr - , ptr_or_ptr_ref_lvalue_from_python_chain - , ref_lvalue_from_python_chain - >::type type; - }; -} - -template -struct lvalue_from_python_chain - : detail::select_lvalue_from_python_chain::type -{ -}; - -}}} // namespace boost::python::converter - -#endif // LVALUE_FROM_PYTHON_CHAIN_DWA200237_HPP diff --git a/include/boost/python/converter/pointee_from_python.hpp b/include/boost/python/converter/pointee_from_python.hpp new file mode 100644 index 00000000..1274f237 --- /dev/null +++ b/include/boost/python/converter/pointee_from_python.hpp @@ -0,0 +1,63 @@ +// Copyright David Abrahams 2002. Permission to copy, use, +// modify, sell and distribute this software is granted provided this +// copyright notice appears in all copies. This software is provided +// "as is" without express or implied warranty, and with no claim as +// to its suitability for any purpose. +#ifndef POINTEE_FROM_PYTHON_DWA2002710_HPP +# define POINTEE_FROM_PYTHON_DWA2002710_HPP +# include +# include +# include +# include +# include + +namespace boost { namespace python { namespace converter { + +struct from_python_registration; + +# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +template +struct pointee_from_python + : from_python< + typename remove_pointer< + typename remove_cv< + typename remove_reference::type + >::type + >::type + > +{ +}; +# else +namespace detail +{ + template + struct pointee_from_python_base + { + static from_python_registration const& converters; + }; +} + +template +struct pointee_from_python + : detail::pointee_from_python_base< + typename add_reference< + typename add_cv::type + >::type + > +{ +}; + +// +// implementations +// +namespace detail +{ + template + from_python_registration const& pointee_from_python_base::converters + = registry::from_python_converters(pointer_type_id()); +} + +# endif +}}} // namespace boost::python::converter + +#endif // POINTEE_FROM_PYTHON_DWA2002710_HPP diff --git a/include/boost/python/converter/registrations.hpp b/include/boost/python/converter/registrations.hpp index eed1768a..fd1e4385 100644 --- a/include/boost/python/converter/registrations.hpp +++ b/include/boost/python/converter/registrations.hpp @@ -8,22 +8,41 @@ # include # include +# include namespace boost { namespace python { namespace converter { -struct lvalue_from_python_registration +struct lvalue_from_python_chain { convertible_function convert; - lvalue_from_python_registration* next; + lvalue_from_python_chain* next; }; -struct rvalue_from_python_registration +struct rvalue_from_python_chain { convertible_function convertible; constructor_function construct; - rvalue_from_python_registration* next; + rvalue_from_python_chain* next; }; +struct from_python_registration +{ + explicit from_python_registration(type_info); + + const python::type_info target_type; + lvalue_from_python_chain* lvalue_chain; + rvalue_from_python_chain* rvalue_chain; +}; + +// +// implementations +// +inline from_python_registration::from_python_registration(type_info target_type) + : target_type(target_type) + , lvalue_chain(0) + , rvalue_chain(0) +{} + }}} // namespace boost::python::converter #endif // REGISTRATIONS_DWA2002223_HPP diff --git a/include/boost/python/converter/registry.hpp b/include/boost/python/converter/registry.hpp index a686205c..07058bcb 100644 --- a/include/boost/python/converter/registry.hpp +++ b/include/boost/python/converter/registry.hpp @@ -15,14 +15,12 @@ namespace boost { namespace python { namespace converter { -struct lvalue_from_python_registration; -struct rvalue_from_python_registration; +struct from_python_registration; // This namespace acts as a sort of singleton namespace registry { - BOOST_PYTHON_DECL lvalue_from_python_registration*& lvalue_converters(type_info); - BOOST_PYTHON_DECL rvalue_from_python_registration*& rvalue_converters(type_info); + BOOST_PYTHON_DECL from_python_registration const& from_python_converters(type_info); BOOST_PYTHON_DECL to_python_function_t const& get_to_python_function(type_info); diff --git a/include/boost/python/converter/return_from_python.hpp b/include/boost/python/converter/return_from_python.hpp index 9bfca7ec..077405f7 100755 --- a/include/boost/python/converter/return_from_python.hpp +++ b/include/boost/python/converter/return_from_python.hpp @@ -8,11 +8,12 @@ # include # include -# include -# include +# include # include # include # include +# include +# include namespace boost { namespace python { namespace converter { @@ -22,7 +23,6 @@ namespace detail struct return_pointer_from_python { typedef T result_type; - return_pointer_from_python(); T operator()(PyObject*) const; }; @@ -30,7 +30,6 @@ namespace detail struct return_reference_from_python { typedef T result_type; - return_reference_from_python(); T operator()(PyObject*) const; }; @@ -93,9 +92,10 @@ namespace detail { template inline return_rvalue_from_python::return_rvalue_from_python() - : m_data(rvalue_from_python_chain::value) + : m_data( + const_cast(&from_python::converters) + ) { - throw_if_not_registered(m_data.stage1); } template @@ -105,30 +105,18 @@ namespace detail return *(T*)convert_rvalue(obj, m_data.stage1, m_data.storage.bytes); } - template - inline return_reference_from_python::return_reference_from_python() - { - detail::throw_if_not_registered(lvalue_from_python_chain::value); - } - template inline T return_reference_from_python::operator()(PyObject* obj) const { return python::detail::void_ptr_to_reference( - callback_convert_reference(obj, lvalue_from_python_chain::value) + callback_convert_reference(obj, from_python::converters) , (T(*)())0); } - template - inline return_pointer_from_python::return_pointer_from_python() - { - detail::throw_if_not_registered(lvalue_from_python_chain::value); - } - template inline T return_pointer_from_python::operator()(PyObject* obj) const { - return T(callback_convert_pointer(obj, lvalue_from_python_chain::value)); + return T(callback_convert_pointer(obj, pointee_from_python::converters)); } } diff --git a/src/converter/callback.cpp b/src/converter/callback.cpp index bf72e9e6..04ad5606 100644 --- a/src/converter/callback.cpp +++ b/src/converter/callback.cpp @@ -7,8 +7,10 @@ #include #include #include +#include #include #include +#include namespace boost { namespace python { namespace converter { @@ -43,46 +45,30 @@ namespace detail { } - BOOST_PYTHON_DECL void throw_if_not_registered(rvalue_from_python_stage1_data const& data) - { - if (!data.convertible) - { - PyErr_SetString( - PyExc_TypeError - , const_cast("no from_python rvalue or lvalue converters found for type")); - throw_error_already_set(); - } - } - - BOOST_PYTHON_DECL void throw_if_not_registered(lvalue_from_python_registration*const& x) - { - if (!x) - { - PyErr_SetString( - PyExc_TypeError - , const_cast("no from_python lvalue converters found for type")); - throw_error_already_set(); - } - } - BOOST_PYTHON_DECL void* callback_convert_reference( PyObject* source - , lvalue_from_python_registration*const& converters) + , from_python_registration const& converters) { handle<> holder(source); if (source->ob_refcnt <= 2) { - PyErr_SetString( + PyErr_SetObject( PyExc_ReferenceError - , const_cast("Attempt to return dangling internal reference")); + , (object("Attempt to return dangling pointer/reference to object of type ") + + converters.target_type.name()).ptr() + ); throw_error_already_set(); } - void* result = find(source, converters); + void* result = get_lvalue_from_python(source, converters); if (!result) { - PyErr_SetString( + handle<> repr(PyObject_Repr(source)); + PyErr_SetObject( PyExc_TypeError - , const_cast("no registered from_python lvalue converter was able to convert object")); + , (object("no registered converter was able to convert ") + + repr + " to a C++ lvalue of type " + + converters.target_type.name()).ptr() + ); throw_error_already_set(); } return result; @@ -90,7 +76,7 @@ namespace detail BOOST_PYTHON_DECL void* callback_convert_pointer( PyObject* source - , lvalue_from_python_registration*const& converters) + , from_python_registration const& converters) { if (source == Py_None) { @@ -112,7 +98,8 @@ namespace detail { handle<> holder(src); - data = find(src, static_cast(data.convertible)); + data = rvalue_from_python_stage1( + src, *static_cast(data.convertible)); if (!data.convertible) { diff --git a/src/converter/from_python.cpp b/src/converter/from_python.cpp index 826f453c..da7bde38 100644 --- a/src/converter/from_python.cpp +++ b/src/converter/from_python.cpp @@ -14,10 +14,12 @@ namespace boost { namespace python { namespace converter { -BOOST_PYTHON_DECL rvalue_from_python_stage1_data find( +BOOST_PYTHON_DECL rvalue_from_python_stage1_data rvalue_from_python_stage1( PyObject* source - , rvalue_from_python_registration const* chain) + , from_python_registration const& converters) { + rvalue_from_python_chain const* chain = converters.rvalue_chain; + rvalue_from_python_stage1_data data; data.convertible = 0; for (;chain != 0; chain = chain->next) @@ -33,23 +35,54 @@ BOOST_PYTHON_DECL rvalue_from_python_stage1_data find( return data; } +BOOST_PYTHON_DECL void* get_lvalue_from_python( + PyObject* source + , from_python_registration const& converters) +{ + lvalue_from_python_chain const* chain = converters.lvalue_chain; + + for (;chain != 0; chain = chain->next) + { + void* r = chain->convert(source); + if (r != 0) + return r; + } + return 0; +} + namespace { // Prevent looping in implicit conversions. This could/should be // much more efficient, but will work for now. - typedef std::vector visited_t; + typedef std::vector visited_t; static visited_t visited; + + inline bool visit(rvalue_from_python_chain const* chain) + { + visited_t::iterator const p = std::lower_bound(visited.begin(), visited.end(), chain); + if (p != visited.end() && *p == chain) + return false; + visited.insert(p, chain); + return true; + } + + void unvisit(rvalue_from_python_chain const* chain) + { + visited_t::iterator const p = std::lower_bound(visited.begin(), visited.end(), chain); + assert(p != visited.end()); + visited.erase(p); + } } -BOOST_PYTHON_DECL rvalue_from_python_registration const* find_chain( +BOOST_PYTHON_DECL rvalue_from_python_chain const* implicit_conversion_chain( PyObject* source - , rvalue_from_python_registration const* chain) + , from_python_registration const& converters) { - visited_t::iterator p = std::lower_bound(visited.begin(), visited.end(), chain); - if (p != visited.end() && *p == chain) + rvalue_from_python_chain const* chain = converters.rvalue_chain; + + if (!visit(chain)) return 0; - visited.insert(p, chain); try { for (;chain != 0; chain = chain->next) @@ -60,25 +93,11 @@ BOOST_PYTHON_DECL rvalue_from_python_registration const* find_chain( } catch(...) { - visited.erase(p); + unvisit(chain); throw; } - p = std::lower_bound(visited.begin(), visited.end(), chain); - visited.erase(p); + unvisit(chain); return chain; } -BOOST_PYTHON_DECL void* find( - PyObject* source - , lvalue_from_python_registration const* chain) -{ - for (;chain != 0; chain = chain->next) - { - void* r = chain->convert(source); - if (r != 0) - return r; - } - return 0; -} - }}} // namespace boost::python::converter diff --git a/src/converter/registry.cpp b/src/converter/registry.cpp index d1ba57df..05256ded 100644 --- a/src/converter/registry.cpp +++ b/src/converter/registry.cpp @@ -6,7 +6,7 @@ #include #include #include -#include +#include #include namespace boost { namespace python { namespace converter { @@ -16,21 +16,23 @@ namespace // // These are the elements stored in the registry struct entry { - entry(); + entry(type_info target); + + from_python_registration m_from_python; // The unique to_python converter for the associated C++ type. to_python_function_t m_to_python_converter; - // The collection of from_python converters for the associated - // C++ type. - lvalue_from_python_registration* m_lvalue_from_python; - rvalue_from_python_registration* m_rvalue_from_python; - // The class object associated with this type PyTypeObject* m_class_object; }; + + inline bool operator<(entry const& lhs, entry const& rhs) + { + return lhs.m_from_python.target_type < rhs.m_from_python.target_type; + } - typedef std::map registry_t; + typedef std::set registry_t; registry_t& entries() { @@ -50,19 +52,16 @@ namespace // return registry; } - entry* find(type_info type) + entry* get(type_info type) { - registry_t& assoc = entries(); - registry_t::iterator p = assoc.find(type); - return p != assoc.end() - ? &p->second - : &assoc[type]; + return const_cast( + &*entries().insert(entry(type)).first + ); } - entry::entry() - : m_to_python_converter(0) - , m_lvalue_from_python(0) - , m_rvalue_from_python(0) + entry::entry(type_info target) + : m_from_python(target) + , m_to_python_converter(0) , m_class_object(0) { } @@ -73,12 +72,12 @@ namespace registry to_python_function_t const& get_to_python_function( type_info key) { - return find(key)->m_to_python_converter; + return get(key)->m_to_python_converter; } void insert(to_python_function_t f, type_info source_t) { - to_python_function_t& slot = find(source_t)->m_to_python_converter; + to_python_function_t& slot = get(source_t)->m_to_python_converter; assert(slot == 0); // we have a problem otherwise if (slot != 0) { @@ -89,13 +88,13 @@ namespace registry } // Insert an lvalue from_python converter - void insert(void* (*convert)(PyObject*), type_info key) + void insert(convertible_function convert, type_info key) { - entry* found = find(key); - lvalue_from_python_registration *registration = new lvalue_from_python_registration; + entry* found = get(key); + lvalue_from_python_chain *registration = new lvalue_from_python_chain; registration->convert = convert; - registration->next = found->m_lvalue_from_python; - found->m_lvalue_from_python = registration; + registration->next = found->m_from_python.lvalue_chain; + found->m_from_python.lvalue_chain = registration; insert(convert, 0, key); } @@ -105,12 +104,12 @@ namespace registry , constructor_function construct , type_info key) { - entry* found = find(key); - rvalue_from_python_registration *registration = new rvalue_from_python_registration; + entry* found = get(key); + rvalue_from_python_chain *registration = new rvalue_from_python_chain; registration->convertible = convertible; registration->construct = construct; - registration->next = found->m_rvalue_from_python; - found->m_rvalue_from_python = registration; + registration->next = found->m_from_python.rvalue_chain; + found->m_from_python.rvalue_chain = registration; } // Insert an rvalue from_python converter @@ -118,11 +117,11 @@ namespace registry , constructor_function construct , type_info key) { - rvalue_from_python_registration** found = &find(key)->m_rvalue_from_python; + rvalue_from_python_chain** found = &get(key)->m_from_python.rvalue_chain; while (*found != 0) found = &(*found)->next; - rvalue_from_python_registration *registration = new rvalue_from_python_registration; + rvalue_from_python_chain *registration = new rvalue_from_python_chain; registration->convertible = convertible; registration->construct = construct; registration->next = 0; @@ -131,19 +130,13 @@ namespace registry PyTypeObject*& class_object(type_info key) { - return find(key)->m_class_object; + return get(key)->m_class_object; } - lvalue_from_python_registration*& lvalue_converters(type_info key) + from_python_registration const& from_python_converters(type_info key) { - return find(key)->m_lvalue_from_python; + return get(key)->m_from_python; } - - rvalue_from_python_registration*& rvalue_converters(type_info key) - { - return find(key)->m_rvalue_from_python; - } - } // namespace registry }}} // namespace boost::python::converter