From 149c60bd2e28e740766a10eeecfee85309f80fc9 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 14 Jul 2002 23:25:56 +0000 Subject: [PATCH] Still further rationalized conversion registry [SVN r14462] --- Jamfile | 2 +- .../python/converter/arg_from_python.hpp | 2 +- .../converter/callback_from_python_base.hpp | 24 --- .../{find_from_python.hpp => from_python.hpp} | 13 +- .../python/converter/return_from_python.hpp | 10 +- src/converter/arg_to_python_base.cpp | 58 +++++++ src/converter/callback.cpp | 141 ------------------ src/converter/from_python.cpp | 94 +++++++++++- 8 files changed, 167 insertions(+), 177 deletions(-) delete mode 100644 include/boost/python/converter/callback_from_python_base.hpp rename include/boost/python/converter/{find_from_python.hpp => from_python.hpp} (76%) create mode 100644 src/converter/arg_to_python_base.cpp delete mode 100644 src/converter/callback.cpp diff --git a/Jamfile b/Jamfile index b28cf262..192982f6 100644 --- a/Jamfile +++ b/Jamfile @@ -27,7 +27,7 @@ dll bpl src/module.cpp src/objects2.cpp src/converter/builtin_converters.cpp - src/converter/callback.cpp + src/converter/arg_to_python_base.cpp src/object/iterator.cpp src/object_protocol.cpp src/object_operators.cpp diff --git a/include/boost/python/converter/arg_from_python.hpp b/include/boost/python/converter/arg_from_python.hpp index 351e8a2e..7bca5040 100755 --- a/include/boost/python/converter/arg_from_python.hpp +++ b/include/boost/python/converter/arg_from_python.hpp @@ -6,7 +6,7 @@ #ifndef ARG_FROM_PYTHON_DWA2002127_HPP # define ARG_FROM_PYTHON_DWA2002127_HPP -# include +# include # include # include # include diff --git a/include/boost/python/converter/callback_from_python_base.hpp b/include/boost/python/converter/callback_from_python_base.hpp deleted file mode 100644 index 95bd2187..00000000 --- a/include/boost/python/converter/callback_from_python_base.hpp +++ /dev/null @@ -1,24 +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 CALLBACK_FROM_PYTHON_BASE_DWA200237_HPP -# define CALLBACK_FROM_PYTHON_BASE_DWA200237_HPP - -namespace boost { namespace python { namespace converter { - -struct rvalue_from_python_stage1_data; -struct registration; - -namespace detail -{ - BOOST_PYTHON_DECL void* convert_rvalue(PyObject*, rvalue_from_python_stage1_data&, void* storage); - BOOST_PYTHON_DECL void* callback_convert_reference(PyObject*, registration const&); - BOOST_PYTHON_DECL void* callback_convert_pointer(PyObject*, registration const&); - BOOST_PYTHON_DECL void absorb_result(PyObject*); -} - -}}} // namespace boost::python::converter - -#endif // CALLBACK_FROM_PYTHON_BASE_DWA200237_HPP diff --git a/include/boost/python/converter/find_from_python.hpp b/include/boost/python/converter/from_python.hpp similarity index 76% rename from include/boost/python/converter/find_from_python.hpp rename to include/boost/python/converter/from_python.hpp index 629eec92..ac8b4894 100644 --- a/include/boost/python/converter/find_from_python.hpp +++ b/include/boost/python/converter/from_python.hpp @@ -18,11 +18,20 @@ struct rvalue_from_python_chain; BOOST_PYTHON_DECL void* get_lvalue_from_python( PyObject* source, registration const&); +BOOST_PYTHON_DECL rvalue_from_python_chain const* implicit_conversion_chain( + PyObject* source, registration const&); + BOOST_PYTHON_DECL rvalue_from_python_stage1_data rvalue_from_python_stage1( PyObject* source, registration const&); -BOOST_PYTHON_DECL rvalue_from_python_chain const* implicit_conversion_chain( - PyObject* source, registration const&); +BOOST_PYTHON_DECL void* rvalue_from_python_stage2( + PyObject*, rvalue_from_python_stage1_data&, void* storage); + +BOOST_PYTHON_DECL void* reference_from_python(PyObject*, registration const&); +BOOST_PYTHON_DECL void* pointer_from_python(PyObject*, registration const&); + +BOOST_PYTHON_DECL void void_from_python(PyObject*); + }}} // namespace boost::python::converter diff --git a/include/boost/python/converter/return_from_python.hpp b/include/boost/python/converter/return_from_python.hpp index 8f9f31b3..902612e2 100755 --- a/include/boost/python/converter/return_from_python.hpp +++ b/include/boost/python/converter/return_from_python.hpp @@ -6,7 +6,7 @@ #ifndef RETURN_FROM_PYTHON_DWA200265_HPP # define RETURN_FROM_PYTHON_DWA200265_HPP -# include +# include # include # include # include @@ -77,7 +77,7 @@ struct return_from_python result_type operator()(PyObject* x) const { - converter::detail::absorb_result(x); + converter::void_from_python(x); # ifdef BOOST_NO_VOID_RETURNS return result_type(); # endif @@ -101,21 +101,21 @@ namespace detail inline typename return_rvalue_from_python::result_type return_rvalue_from_python::operator()(PyObject* obj) { - return *(T*)convert_rvalue(obj, m_data.stage1, m_data.storage.bytes); + return *(T*)rvalue_from_python_stage2(obj, m_data.stage1, m_data.storage.bytes); } template inline T return_reference_from_python::operator()(PyObject* obj) const { return python::detail::void_ptr_to_reference( - callback_convert_reference(obj, registered::converters) + reference_from_python(obj, registered::converters) , (T(*)())0); } template inline T return_pointer_from_python::operator()(PyObject* obj) const { - return T(callback_convert_pointer(obj, registered_pointee::converters)); + return T(pointer_from_python(obj, registered_pointee::converters)); } } diff --git a/src/converter/arg_to_python_base.cpp b/src/converter/arg_to_python_base.cpp new file mode 100644 index 00000000..7936216a --- /dev/null +++ b/src/converter/arg_to_python_base.cpp @@ -0,0 +1,58 @@ +// 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. + +#include +#include +#include +#include +#include + +namespace boost { namespace python { namespace converter { + +namespace +{ + inline PyObject* convert_to_python(void const volatile* source, registration const& converters) + { + if (converters.to_python == 0) + { + handle<> msg( + ::PyString_FromFormat( + "No to_python (by-value) converter found for C++ type: %s" + , converters.target_type.name())); + + PyErr_SetObject(PyExc_TypeError, msg.get()); + + throw_error_already_set(); + } + + return source == 0 + ? incref(Py_None) + : converters.to_python(const_cast(source)); + } +} + +namespace detail +{ + arg_to_python_base::arg_to_python_base( + void const volatile* source, registration const& converters) +# if !defined(BOOST_MSVC) || _MSC_FULL_VER != 13102140 + : handle<>(converter::convert_to_python(source, converters)) +# else + : m_ptr(converter::convert_to_python(source, converters)) +# endif + { + } + + BOOST_PYTHON_DECL void throw_no_class_registered() + { + PyErr_SetString( + PyExc_TypeError + , const_cast("class not registered for to_python type")); + throw_error_already_set(); + } +} + +}}} // namespace boost::python::converter diff --git a/src/converter/callback.cpp b/src/converter/callback.cpp deleted file mode 100644 index 827d1e07..00000000 --- a/src/converter/callback.cpp +++ /dev/null @@ -1,141 +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. - -#include -#include -#include -#include -#include -#include -#include - -namespace boost { namespace python { namespace converter { - -namespace detail -{ - - namespace - { - inline PyObject* convert_to_python(void const volatile* source, registration const& converters) - { - if (converters.to_python == 0) - { - handle<> msg( - ::PyString_FromFormat( - "No to_python (by-value) converter found for C++ type: %s" - , converters.target_type.name())); - - PyErr_SetObject(PyExc_TypeError, msg.get()); - - throw_error_already_set(); - } - - return source == 0 - ? python::detail::none() - : converters.to_python(const_cast(source)); - } - } - - arg_to_python_base::arg_to_python_base( - void const volatile* source, registration const& converters) -# if !defined(BOOST_MSVC) || _MSC_FULL_VER != 13102140 - : handle<>(convert_to_python(source, converters)) -# else - : m_ptr(convert_to_python(source, converters)) -# endif - { - } - - BOOST_PYTHON_DECL void* callback_convert_reference( - PyObject* source - , registration const& converters) - { - handle<> holder(source); - if (source->ob_refcnt <= 2) - { - handle<> msg( - ::PyString_FromFormat( - "Attempt to return dangling pointer/reference to object of type: %s" - , converters.target_type.name())); - - PyErr_SetObject(PyExc_ReferenceError, msg.get()); - - throw_error_already_set(); - } - void* result = get_lvalue_from_python(source, converters); - if (!result) - { - handle<> msg( - ::PyString_FromFormat( - "No registered converter was able to extract a a C++ lvalue of type %s from this Python object of type %s" - , converters.target_type.name() - , source->ob_type->tp_name - )); - - PyErr_SetObject(PyExc_TypeError, msg.get()); - - throw_error_already_set(); - } - return result; - } - - BOOST_PYTHON_DECL void* callback_convert_pointer( - PyObject* source - , registration const& converters) - { - if (source == Py_None) - { - Py_DECREF(source); - return 0; - } - return callback_convert_reference(source, converters); - } - - BOOST_PYTHON_DECL void throw_no_class_registered() - { - PyErr_SetString( - PyExc_TypeError - , const_cast("class not registered for to_python type")); - throw_error_already_set(); - } - - BOOST_PYTHON_DECL void* convert_rvalue(PyObject* src, rvalue_from_python_stage1_data& data, void* storage) - { - handle<> holder(src); - - void const* converters_ = data.convertible; - registration const& converters = *static_cast(converters_); - data = rvalue_from_python_stage1(src, converters); - - if (!data.convertible) - { - handle<> msg( - ::PyString_FromFormat( - "No registered converter was able to produce a C++ lvalue of type %s from this Python object of type %s" - , converters.target_type.name() - , src->ob_type->tp_name - )); - - PyErr_SetObject(PyExc_TypeError, msg.get()); - throw_error_already_set(); - } - - // If a construct function was registered (i.e. we found an - // rvalue conversion), call it now. - if (data.construct != 0) - data.construct(src, &data); - - // Return the address of the resulting C++ object - return data.convertible; - } - - BOOST_PYTHON_DECL void absorb_result(PyObject* o) - { - Py_DECREF(expect_non_null(o)); - } -} - -}}} // namespace boost::python::converter diff --git a/src/converter/from_python.cpp b/src/converter/from_python.cpp index f68bf0fa..b9dc8614 100644 --- a/src/converter/from_python.cpp +++ b/src/converter/from_python.cpp @@ -4,11 +4,10 @@ // "as is" without express or implied warranty, and with no claim as // to its suitability for any purpose. -#include +#include #include #include -#include -#include +#include #include #include @@ -35,6 +34,37 @@ BOOST_PYTHON_DECL rvalue_from_python_stage1_data rvalue_from_python_stage1( return data; } +BOOST_PYTHON_DECL void* rvalue_from_python_stage2( + PyObject* src, rvalue_from_python_stage1_data& data, void* storage) +{ + handle<> holder(src); + + void const* converters_ = data.convertible; + registration const& converters = *static_cast(converters_); + data = rvalue_from_python_stage1(src, converters); + + if (!data.convertible) + { + handle<> msg( + ::PyString_FromFormat( + "No registered converter was able to produce a C++ lvalue of type %s from this Python object of type %s" + , converters.target_type.name() + , src->ob_type->tp_name + )); + + PyErr_SetObject(PyExc_TypeError, msg.get()); + throw_error_already_set(); + } + + // If a construct function was registered (i.e. we found an + // rvalue conversion), call it now. + if (data.construct != 0) + data.construct(src, &data); + + // Return the address of the resulting C++ object + return data.convertible; +} + BOOST_PYTHON_DECL void* get_lvalue_from_python( PyObject* source , registration const& converters) @@ -100,4 +130,62 @@ BOOST_PYTHON_DECL rvalue_from_python_chain const* implicit_conversion_chain( return chain; } +BOOST_PYTHON_DECL void* reference_from_python( + PyObject* source + , registration const& converters) +{ + handle<> holder(source); + if (source->ob_refcnt <= 2) + { + handle<> msg( + ::PyString_FromFormat( + "Attempt to return dangling pointer/reference to object of type: %s" + , converters.target_type.name())); + + PyErr_SetObject(PyExc_ReferenceError, msg.get()); + + throw_error_already_set(); + } + void* result = get_lvalue_from_python(source, converters); + if (!result) + { + handle<> msg( + ::PyString_FromFormat( + "No registered converter was able to extract a a C++ lvalue of type %s from this Python object of type %s" + , converters.target_type.name() + , source->ob_type->tp_name + )); + + PyErr_SetObject(PyExc_TypeError, msg.get()); + + throw_error_already_set(); + } + return result; +} + +BOOST_PYTHON_DECL void* pointer_from_python( + PyObject* source + , registration const& converters) +{ + if (source == Py_None) + { + Py_DECREF(source); + return 0; + } + return reference_from_python(source, converters); +} + +BOOST_PYTHON_DECL void throw_no_class_registered() +{ + PyErr_SetString( + PyExc_TypeError + , const_cast("class not registered for to_python type")); + throw_error_already_set(); +} + +BOOST_PYTHON_DECL void void_from_python(PyObject* o) +{ + Py_DECREF(expect_non_null(o)); +} + }}} // namespace boost::python::converter