From ac34e0e1086709b5f070bf45fc4f0a7c30772b9e Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Tue, 26 Mar 2002 06:38:41 +0000 Subject: [PATCH] implicit conversions [SVN r13277] --- .../python/converter/find_from_python.hpp | 3 ++ include/boost/python/converter/implicit.hpp | 50 +++++++++++++++++++ include/boost/python/implicit.hpp | 28 +++++++++++ include/boost/python/type_from_python.hpp | 2 +- src/converter/from_python.cpp | 12 +++++ test/Jamfile | 1 + test/implicit.cpp | 37 ++++++++++++++ test/implicit.py | 20 ++++++++ test/test_class.hpp | 31 ++++++++++++ 9 files changed, 183 insertions(+), 1 deletion(-) create mode 100644 include/boost/python/converter/implicit.hpp create mode 100644 include/boost/python/implicit.hpp create mode 100644 test/implicit.cpp create mode 100644 test/implicit.py create mode 100644 test/test_class.hpp diff --git a/include/boost/python/converter/find_from_python.hpp b/include/boost/python/converter/find_from_python.hpp index e7f7ca81..709c5de0 100644 --- a/include/boost/python/converter/find_from_python.hpp +++ b/include/boost/python/converter/find_from_python.hpp @@ -21,6 +21,9 @@ BOOST_PYTHON_DECL void* find( BOOST_PYTHON_DECL rvalue_stage1_data find( PyObject* source, rvalue_from_python_registration const*); +BOOST_PYTHON_DECL rvalue_from_python_registration const* find_chain( + PyObject* source, rvalue_from_python_registration const*); + }}} // namespace boost::python::converter #endif // FIND_FROM_PYTHON_DWA2002223_HPP diff --git a/include/boost/python/converter/implicit.hpp b/include/boost/python/converter/implicit.hpp new file mode 100644 index 00000000..95372810 --- /dev/null +++ b/include/boost/python/converter/implicit.hpp @@ -0,0 +1,50 @@ +// 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 IMPLICIT_DWA2002326_HPP +# define IMPLICIT_DWA2002326_HPP +# include +# include +# include + +namespace boost { namespace python { namespace converter { + +template +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)); + } + + static void construct(PyObject* obj, rvalue_stage1_data* data) + { + // This is the registration we got from the convertible step + rvalue_from_python_registration const* registration + = static_cast(data->convertible); + + // Call the convertible function again + rvalue_data intermediate_data(registration->convertible(obj)); + + // Use the result to construct the source type if the first + // converter was an rvalue converter. + if (registration->construct != 0) + registration->construct(obj, &intermediate_data.stage1); + + void* storage = ((rvalue_base_data*)data)->storage.bytes; + new (storage) Target(*(Source*)intermediate_data.storage.bytes); + + // record successful construction + data->convertible = storage; + + } +}; + +}}} // namespace boost::python::converter + +#endif // IMPLICIT_DWA2002326_HPP diff --git a/include/boost/python/implicit.hpp b/include/boost/python/implicit.hpp new file mode 100644 index 00000000..b13898e8 --- /dev/null +++ b/include/boost/python/implicit.hpp @@ -0,0 +1,28 @@ +// 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 IMPLICIT_DWA2002325_HPP +# define IMPLICIT_DWA2002325_HPP +# include +# include +# include +# include + +namespace boost { namespace python { + +template +void implicitly_convertible(boost::type* = 0, boost::type* = 0) +{ + typedef converter::implicit functions; + + converter::registry::insert( + &functions::convertible + , &functions::construct + , converter::undecorated_type_id()); +} + +}} // namespace boost::python + +#endif // IMPLICIT_DWA2002325_HPP diff --git a/include/boost/python/type_from_python.hpp b/include/boost/python/type_from_python.hpp index d5b9faed..38d2ceea 100644 --- a/include/boost/python/type_from_python.hpp +++ b/include/boost/python/type_from_python.hpp @@ -22,7 +22,7 @@ namespace detail } // A function generator whose static execute() function is an lvalue - // from_python converter using the given Extractor. U is exepcted to + // from_python converter using the given Extractor. U is expected to // be the actual type of the PyObject instance from which the result // is being extracted. template diff --git a/src/converter/from_python.cpp b/src/converter/from_python.cpp index 8a68cc44..f821201a 100644 --- a/src/converter/from_python.cpp +++ b/src/converter/from_python.cpp @@ -29,6 +29,18 @@ BOOST_PYTHON_DECL rvalue_stage1_data find( return data; } +BOOST_PYTHON_DECL rvalue_from_python_registration const* find_chain( + PyObject* source + , rvalue_from_python_registration const* chain) +{ + for (;chain != 0; chain = chain->next) + { + if (chain->convertible(source)) + break; + } + return chain; +} + BOOST_PYTHON_DECL void* find( PyObject* source , lvalue_from_python_registration const* chain) diff --git a/test/Jamfile b/test/Jamfile index 9809c5db..52253f2a 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -57,6 +57,7 @@ bpl-test test_pointer_adoption ; bpl-test callbacks ; bpl-test virtual_functions ; bpl-test back_reference ; +bpl-test implicit ; # --- unit tests of library components --- unit-test indirect_traits_test diff --git a/test/implicit.cpp b/test/implicit.cpp new file mode 100644 index 00000000..17cbe7f7 --- /dev/null +++ b/test/implicit.cpp @@ -0,0 +1,37 @@ +// 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 "test_class.hpp" + +// This test shows that a class can be wrapped "as itself" but also +// acquire a back-reference iff has_back_reference<> is appropriately +// specialized. +using namespace boost::python; + +typedef test_class<> X; + +int x_value(X const& x) +{ + return x.value(); +} + +BOOST_PYTHON_MODULE_INIT(implicit_ext) +{ + implicitly_convertible(); + module("implicit_ext") + .def("x_value", x_value) + .add( + class_("X") + .def_init(args()) + .def("value", &X::value) + .def("set", &X::set) + ) + ; +} + +#include "module_tail.cpp" diff --git a/test/implicit.py b/test/implicit.py new file mode 100644 index 00000000..322467c0 --- /dev/null +++ b/test/implicit.py @@ -0,0 +1,20 @@ +''' +>>> from implicit_ext import * +>>> x_value(X(42)) +42 +>>> x_value(42) +42 +''' + +def run(args = None): + import sys + import doctest + + if args is not None: + sys.argv = args + return doctest.testmod(sys.modules.get(__name__)) + +if __name__ == '__main__': + print "running..." + import sys + sys.exit(run()[0]) diff --git a/test/test_class.hpp b/test/test_class.hpp new file mode 100644 index 00000000..920a6b1f --- /dev/null +++ b/test/test_class.hpp @@ -0,0 +1,31 @@ +// 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 TEST_CLASS_DWA2002326_HPP +# define TEST_CLASS_DWA2002326_HPP +# include + +template +struct test_class +{ + explicit test_class(int x) : x(x), magic(7654321 + n) { ++counter; } + test_class(test_class const& rhs) : x(rhs.x), magic(7654321 + n) { ++counter; } + virtual ~test_class() { assert(magic == 7654321 + n); magic = 6666666; x = 9999; --counter; } + + void set(int x) { assert(magic == 7654321 + n); this->x = x; } + int value() const { assert(magic == 7654321 + n); return x; } + static int count() { return counter; } + private: + void operator=(test_class const&); + private: + int x; + long magic; + static int counter; +}; + +template +int test_class::counter; + +#endif // TEST_CLASS_DWA2002326_HPP