diff --git a/include/boost/python/convert.hpp b/include/boost/python/convert.hpp deleted file mode 100644 index 5614bd3b..00000000 --- a/include/boost/python/convert.hpp +++ /dev/null @@ -1,84 +0,0 @@ -// Copyright David Abrahams 2001. 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 CONVERT_DWA20011129_HPP -# define CONVERT_DWA20011129_HPP - -# include -# include -# include -# include - -namespace boost { namespace python { - -namespace detail -{ - template - struct converter_gen - { - typedef T value_type; - typedef typename converter::source::type source_t; - typedef converter::wrap_ wrap_t; - typedef converter::wrap_more_ wrap_more_t; - - typedef typename converter::target::type target_t; - typedef converter::unwrap_ unwrap_t; - typedef converter::unwrap_more_ unwrap_more_t; - }; -} - -template -struct wrap : detail::converter_gen::wrap_t -{ - typedef typename detail::converter_gen::wrap_t base_t; - typedef typename detail::converter_gen::source_t source_t; -}; - -template -struct wrap_more : detail::converter_gen::wrap_more_t -{ - typedef typename detail::converter_gen::wrap_more_t base_t; - typedef typename detail::converter_gen::source_t source_t; - wrap_more(converter::handle& prev); -}; - -template -struct unwrap : detail::converter_gen::unwrap_t -{ - typedef typename detail::converter_gen::unwrap_t base_t; - unwrap(PyObject*); -}; - -template -struct unwrap_more : detail::converter_gen::unwrap_more_t -{ - typedef typename detail::converter_gen::unwrap_more_t base_t; - unwrap_more(PyObject*, converter::handle& prev); -}; - -// -// implementations -// -template -inline wrap_more::wrap_more(converter::handle& prev) - : base_t(prev) -{ -} - -template -inline unwrap::unwrap(PyObject* source) - : base_t(source) -{ -} - -template -inline unwrap_more::unwrap_more(PyObject* source, converter::handle& prev) - : base_t(source, prev) -{ -} - -}} // namespace boost::python - -#endif // CONVERT_DWA20011129_HPP diff --git a/include/boost/python/converter/body.hpp b/include/boost/python/converter/body.hpp index 72653ee0..d9170839 100644 --- a/include/boost/python/converter/body.hpp +++ b/include/boost/python/converter/body.hpp @@ -10,8 +10,6 @@ namespace boost { namespace python { namespace converter { -struct BOOST_PYTHON_DECL handle; - namespace registry { class entry; @@ -23,9 +21,6 @@ struct BOOST_PYTHON_DECL body body(type_id_t key); virtual ~body() {} - // default implementation is a no-op - virtual void destroy_handle(handle*) const; - type_id_t key() const; protected: diff --git a/include/boost/python/converter/builtin_converters.hpp b/include/boost/python/converter/builtin_converters.hpp new file mode 100644 index 00000000..9c19cbc5 --- /dev/null +++ b/include/boost/python/converter/builtin_converters.hpp @@ -0,0 +1,15 @@ +// 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 BUILTIN_CONVERTERS_DWA2002124_HPP +# define BUILTIN_CONVERTERS_DWA2002124_HPP + +namespace boost { namespace python { namespace converter { + +void initialize_builtin_converters(); + +}}} // namespace boost::python::converter + +#endif // BUILTIN_CONVERTERS_DWA2002124_HPP diff --git a/include/boost/python/converter/builtin_to_python_converters.hpp b/include/boost/python/converter/builtin_to_python_converters.hpp new file mode 100644 index 00000000..4e9f89e3 --- /dev/null +++ b/include/boost/python/converter/builtin_to_python_converters.hpp @@ -0,0 +1,75 @@ +// 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 BUILTIN_TO_PYTHON_CONVERTERS_DWA2002129_HPP +# define BUILTIN_TO_PYTHON_CONVERTERS_DWA2002129_HPP +# include +# include + +namespace boost { namespace python { namespace converter { + +template struct to_python_lookup; + +template +struct to_python_int +{ + bool convertible() const { return true; } + PyObject* operator()(T x) const { return PyInt_FromLong(long(x)); } +}; + +# define BOOST_PYTHON_TO_INT(T) \ + template <> struct to_python_lookup : to_python_int {}; \ + template <> struct to_python_lookup : to_python_int {}; + +BOOST_PYTHON_TO_INT(char) +BOOST_PYTHON_TO_INT(short) +BOOST_PYTHON_TO_INT(int) +BOOST_PYTHON_TO_INT(long) +# undef BOOST_TO_PYTHON_INT + +template <> +struct to_python_lookup +{ + bool convertible() const { return true; } + PyObject* operator()(char const* x) const { return PyString_FromString(x); } +}; + +template <> +struct to_python_lookup +{ + bool convertible() const { return true; } + PyObject* operator()(std::string const& x) const + { + return PyString_FromString(x.c_str()); + } +}; + +template <> +struct to_python_lookup +{ + bool convertible() const { return true; } + PyObject* operator()(float x) const { return PyFloat_FromDouble(x); } +}; + +template <> +struct to_python_lookup +{ + bool convertible() const { return true; } + PyObject* operator()(double x) const { return PyFloat_FromDouble(x); } +}; + +template <> +struct to_python_lookup +{ + bool convertible() const { return true; } + PyObject* operator()(long double x) const + { + return PyFloat_FromDouble(x); + } +}; + +}}} // namespace boost::python::converter + +#endif // BUILTIN_TO_PYTHON_CONVERTERS_DWA2002129_HPP diff --git a/include/boost/python/converter/from_python.hpp b/include/boost/python/converter/from_python.hpp new file mode 100644 index 00000000..234f61d1 --- /dev/null +++ b/include/boost/python/converter/from_python.hpp @@ -0,0 +1,169 @@ +// 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 FROM_PYTHON_DWA2002127_HPP +# define FROM_PYTHON_DWA2002127_HPP + +# include +# include +# include +# include +# include +# include +# include + +namespace boost { namespace python { namespace converter { + +// The type of convertibility checking functions +typedef void* (*from_python_check)(PyObject*); +typedef void (*from_python_destructor)(from_python_data&); + +// forward declaration +template struct from_python_lookup; + +// from_python -- +// A body class representing a conversion from python to C++. + +struct BOOST_PYTHON_DECL from_python_converter_base : body +{ + from_python_converter_base(type_id_t, from_python_check); // registers + ~from_python_converter_base(); // unregisters + + // Must return non-null iff the conversion will be successful. Any + // non-null pointer is acceptable, and will be passed on to the + // convert() function, so useful data can be stored there. + inline void* convertible(PyObject*) const; +// inline type_id_t key() const; + private: +// type_id_t m_key; + from_python_check m_convertible; +}; + + +template +struct from_python_converter : from_python_converter_base +{ + public: // types + typedef typename from_python_function::type conversion_function; + + public: // member functions + from_python_converter(from_python_check, conversion_function, from_python_destructor = 0); + T convert(PyObject*, from_python_data&) const; + void destroy(from_python_data&) const; + + private: // data members + conversion_function m_convert; + from_python_destructor m_destroy; +}; + +// ------------------------------------------------------------------------- + +//struct from_python_base +//{ +//}; + +// A class which implements from_python with a registry lookup. +template +struct from_python_lookup // : from_python_base +{ + public: // types + + public: // member functions + from_python_lookup(PyObject* source); + ~from_python_lookup(); + + bool convertible() const; + T operator()(PyObject*); + + public: // functions for use by conversion implementations + // Get the converter object + from_python_converter const* converter() const; + + private: // data members + typedef typename from_python_intermediate_data::type intermediate_t; + mutable intermediate_t m_intermediate_data; + from_python_converter const* m_converter; +}; + +// +// implementations +// +inline void* from_python_converter_base::convertible(PyObject* o) const +{ + return m_convertible(o); +} + +# if 0 +inline type_id_t from_python_converter_base::key() const +{ + return m_key; +} +# endif + +template +inline from_python_converter::from_python_converter( + from_python_check checker + , conversion_function converter + , from_python_destructor destructor // = 0 + ) + : from_python_converter_base(type_id(), checker) + , m_convert(converter) + , m_destroy(destructor) +{ + +} + +template +inline T from_python_converter::convert(PyObject* src, from_python_data& data) const +{ + return this->m_convert(src, data); +} + +template +inline void from_python_converter::destroy(from_python_data& data) const +{ + if (this->m_destroy) + { + this->m_destroy(data); + } +} + +template +inline from_python_lookup::from_python_lookup(PyObject* src) + : m_converter( + registration::get_from_python( + src, m_intermediate_data.stage1)) +{ +} + +template +inline from_python_lookup::~from_python_lookup() +{ + if (m_converter != 0) + m_converter->destroy(m_intermediate_data); +} + +template +inline bool from_python_lookup::convertible() const +{ + return this->m_converter != 0; +} + +template +inline T from_python_lookup::operator()(PyObject* obj) +{ + return this->m_converter->convert(obj, m_intermediate_data); +} + +template +inline from_python_converter const* +from_python_lookup::converter() const +{ + return this->m_converter; +} + +}}} // namespace boost::python::converter + +#endif // FROM_PYTHON_DWA2002127_HPP diff --git a/include/boost/python/converter/from_python_data.hpp b/include/boost/python/converter/from_python_data.hpp new file mode 100644 index 00000000..3edcbad7 --- /dev/null +++ b/include/boost/python/converter/from_python_data.hpp @@ -0,0 +1,206 @@ +// 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 FROM_PYTHON_AUX_DATA_DWA2002128_HPP +# define FROM_PYTHON_AUX_DATA_DWA2002128_HPP + +# include +# include +# include +# include + +// Keep these for the metaprogram which EDG is choking on. +# if !defined(__EDG__) || (__EDG_VERSION__ > 245) +# include +# include +# include +# include +# endif + +namespace boost { namespace python { namespace converter { + +// A POD which is layout-compatible with the real intermediate data +// for all from_python conversions. There may be additional storage if +// we are converting a reference type. +struct from_python_data +{ + void* stage1; +}; + +namespace detail +{ + template struct referent_alignment; + template struct referent_size; + +# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + + template + struct referent_alignment + { + BOOST_STATIC_CONSTANT( + std::size_t, value = alignment_of::value); + }; + + template + struct referent_size + { + BOOST_STATIC_CONSTANT( + std::size_t, value = sizeof(T)); + }; + +# else + + template + struct alignment_chars + { + BOOST_STATIC_CONSTANT( + std::size_T, n = alignment_of::value); + char elements[n + 1]; + }; + + template struct referent_alignment + { + template + static alignment_chars helper(U&); + + static T t; + + BOOST_STATIC_CONSTANT( + std::size_t, value = sizeof(helper(t).elements) - 1); + }; + + + template struct referent_size + { + static T t; + BOOST_STATIC_CONSTANT(std::size_t, value = sizeof(t)); + }; + +# endif + + struct unknown_alignment + { + void* p; + }; + +// EDG is too slow to handle this metaprogram :( +#if !defined(__EDG__) || (__EDG_VERSION__ > 245) + struct alignment_dummy; + + template + struct best_alignment_type + { + template + struct apply + { + BOOST_STATIC_CONSTANT( + std::size_t, align1 = alignment_of::value); + + BOOST_STATIC_CONSTANT( + std::size_t, align2 = alignment_of::value); + + BOOST_STATIC_CONSTANT( + bool, aligned2 = ( + (align2 >= target_alignment) + & (align2 % target_alignment == 0)) + ); + + BOOST_STATIC_CONSTANT( + bool, choose_t2 = ( + aligned2 && ( + is_same::value + | (align2 < alignment_of::value) + | (sizeof(T2) < sizeof(T1))) + )); + + typedef mpl::select_type::type type; + }; + }; + + typedef mpl::type_list< + char,short,int,long,float,double,long double + ,void* + ,void(*)() + ,void (alignment_dummy::*)() + , char (alignment_dummy::*) + > + align_types; +#endif // EDG is too slow + + template + struct aligned_storage + { + typedef Align align_t; + union + { + Align align; + char bytes[size + // this is just a STATIC_ASSERT. For some reason + // MSVC was barfing on the boost one. + - (is_same::value ? size : 0)]; + }; + }; + + template + struct referent_storage + { +// EDG is too slow to handle this metaprogram :( +#if !defined(__EDG__) || (__EDG_VERSION__ > 245) + typedef mpl::for_each< + align_types + , unknown_alignment + , best_alignment_type::value> + > loop; + typedef typename loop::state align_t; +#else + // The Python source makes the assumption that double has + // maximal alignment anyway + typedef double align_t; +#endif + + typedef aligned_storage::value> type; + }; + + template + struct intermediate_data : from_python_data + { + typename referent_storage::type stage2; + }; + + template <> + struct intermediate_data : from_python_data + { + }; + +} + +// ------------------------------------------------------------------------- +// Auxiliary POD storage where the convertible and/or convert functions of a +// from_python object may place arbitrary data. +// +// Always starts with a void* +// +// For references, we produce additional aligned storage sufficient to +// store the referent + +template +struct from_python_intermediate_data +{ + typedef typename mpl::select_type< + is_reference::value, T, void>::type just_reference_t; + + typedef detail::intermediate_data type; +}; + +template +void* get_storage(from_python_data& x, boost::type* = 0) +{ + typedef typename from_python_intermediate_data::type layout; + return static_cast(&x)->stage2.bytes; +} + +}}} // namespace boost::python::converter + +#endif // FROM_PYTHON_AUX_DATA_DWA2002128_HPP diff --git a/include/boost/python/converter/from_python_function.hpp b/include/boost/python/converter/from_python_function.hpp new file mode 100644 index 00000000..0cf90459 --- /dev/null +++ b/include/boost/python/converter/from_python_function.hpp @@ -0,0 +1,23 @@ +// 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 FROM_PYTHON_FUNCTION_DWA2002128_HPP +# define FROM_PYTHON_FUNCTION_DWA2002128_HPP + +# include + +namespace boost { namespace python { namespace converter { + +struct from_python_data; + +template +struct from_python_function +{ + typedef T (*type)(PyObject*, from_python_data&); +}; + +}}} // namespace boost::python::converter + +#endif // FROM_PYTHON_FUNCTION_DWA2002128_HPP diff --git a/include/boost/python/converter/handle.hpp b/include/boost/python/converter/handle.hpp index 03671634..bc06be38 100644 --- a/include/boost/python/converter/handle.hpp +++ b/include/boost/python/converter/handle.hpp @@ -24,6 +24,7 @@ struct BOOST_PYTHON_DECL handle : boost::noncopyable // // Constructors taking a handle links this into a chain of // handles, for more efficient management in function wrappers + handle(); handle(body* body); handle(body* body, handle& prev); @@ -43,6 +44,9 @@ struct BOOST_PYTHON_DECL handle : boost::noncopyable protected: // member functions for derived classes // Get the body we hold inline body* get_body() const; + + inline void set_body(body*); + inline void set_prev(handle&); // Release all bodies in the chain, in reverse order of // initialization. Only actually called for the head of the chain. @@ -59,6 +63,10 @@ struct BOOST_PYTHON_DECL handle : boost::noncopyable // // implementations // +inline handle::handle() + : m_next(0) +{} + inline handle::handle(body* body, handle& prev) : m_body(body), m_next(0) { @@ -85,6 +93,16 @@ inline body* handle::get_body() const return m_body; } +inline void handle::set_body(body* body) +{ + m_body = body; +} + +inline void handle::set_prev(handle& prev) +{ + prev.m_next = this; +} + }}} // namespace boost::python::converter #endif // HANDLE_DWA20011130_HPP diff --git a/include/boost/python/converter/to_python.hpp b/include/boost/python/converter/to_python.hpp new file mode 100644 index 00000000..61dc7dad --- /dev/null +++ b/include/boost/python/converter/to_python.hpp @@ -0,0 +1,116 @@ +// 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 TO_PYTHON_DWA2002127_HPP +# define TO_PYTHON_DWA2002127_HPP + +# include +# include +# include +# include +# include +# include + +namespace boost { namespace python { namespace converter { + +template struct to_python_lookup; + +struct BOOST_PYTHON_DECL to_python_converter_base : body +{ + to_python_converter_base(type_id_t, to_python_function_base); // registers + ~to_python_converter_base(); // unregisters + +// inline type_id_t key() const; + inline to_python_function_base converter() const; + private: +// type_id_t m_key; + to_python_function_base m_convert; +}; + +template +struct to_python_converter : to_python_converter_base +{ + public: // types + typedef typename to_python_function::type converter_t; + + public: // member functions + to_python_converter(converter_t); + converter_t converter() const; + + private: // data members + converter_t m_convert; +}; + +// ------------------------------------------------------------------------- + +//struct to_python_base {}; + +template +struct to_python_lookup //: to_python_base +{ + public: // member functions + to_python_lookup(); + bool convertible() const; + PyObject* operator()(T) const; + private: + typename to_python_function::type m_convert; +}; + +// +// implementations +// +# if 0 +inline type_id_t +to_python_converter_base::key() const +{ + return m_key; +} +# endif + +inline to_python_function_base +to_python_converter_base::converter() const +{ + return m_convert; +} + +template +to_python_converter::to_python_converter(converter_t convert) + : to_python_converter_base( + type_id(), reinterpret_cast(convert)) +{ +} + +template +inline typename to_python_function::type +to_python_converter::converter() const +{ + return reinterpret_cast( + this->to_python_converter_base::converter()); +} + +template +inline to_python_lookup::to_python_lookup() + : m_convert( + registration::get_to_python()) +{ +} + +template +inline bool +to_python_lookup::convertible() const +{ + return m_converter != 0; +} + +template +inline PyObject* +to_python_lookup::operator()(T x) const +{ + return m_convert ? m_convert(x) : 0; +} + +}}} // namespace boost::python::converter + +#endif // TO_PYTHON_DWA2002127_HPP diff --git a/include/boost/python/converter/to_python_function.hpp b/include/boost/python/converter/to_python_function.hpp new file mode 100644 index 00000000..9d408749 --- /dev/null +++ b/include/boost/python/converter/to_python_function.hpp @@ -0,0 +1,23 @@ +// 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 TO_PYTHON_FUNCTION_DWA2002128_HPP +# define TO_PYTHON_FUNCTION_DWA2002128_HPP + +# include + +namespace boost { namespace python { namespace converter { + +typedef PyObject* (*to_python_function_base)(void); + +template +struct to_python_function +{ + typedef PyObject*(*type)(T); +}; + +}}} // namespace boost::python::converter + +#endif // TO_PYTHON_FUNCTION_DWA2002128_HPP diff --git a/include/boost/python/converter/unwrap.hpp b/include/boost/python/converter/unwrap.hpp deleted file mode 100644 index eccb0992..00000000 --- a/include/boost/python/converter/unwrap.hpp +++ /dev/null @@ -1,172 +0,0 @@ -#error obsolete -// Copyright David Abrahams 2001. 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 UNWRAP_BASE_DWA20011130_HPP -# define UNWRAP_BASE_DWA20011130_HPP - -# include -# include -# include -# include -# include -# include -# include -# include - -namespace boost { namespace python { namespace converter { - -template struct unwrapper; -struct BOOST_PYTHON_DECL body; - -struct BOOST_PYTHON_DECL unwrap_base : handle -{ - public: // member functions - inline unwrap_base(PyObject* source, std::pair, handle& prev); - inline unwrap_base(PyObject* source, std::pair); - inline PyObject* source() const; - - inline void*& data(); - - protected: - inline PyObject*& source(); - - private: // data members - PyObject* m_source; - void* m_data; -}; - -// These converters will be used by the function wrappers. They don't -// manage any resources, but are instead linked into a chain which is -// managed by an instance of unwrap_ or wrap_. -template -struct unwrap_more_ : unwrap_base -{ - public: // member functions - // Construction - unwrap_more_(PyObject* source, handle& prev); - - // invoke the conversion or throw an exception if unsuccessful - T operator*(); - - protected: // constructor - // this constructor is only for the use of unwrap_ - unwrap_more_(PyObject* source); - - private: - typedef typename unwrapper_select::type unwrapper_t; -}; - -// specialization for PyObject* -template <> -struct unwrap_more_ - : unwrap_base -{ - public: // member functions - // Construction - unwrap_more_(PyObject* source, handle& prev) - : unwrap_base(source, m_unwrapper, prev) - { - } - - - // invoke the conversion or throw an exception if unsuccessful - PyObject* operator*() - { - return source(); - } - - void* can_convert(PyObject*) const - { - return &m_unwrapper; - } - - protected: // constructor - // this constructor is only for the use of unwrap_ - unwrap_more_(PyObject* source) - : unwrap_base(source, m_unwrapper) - - { - } - private: - static BOOST_PYTHON_DECL std::pair& m_unwrapper; -}; - -template -struct unwrap_ : unwrap_more_ -{ - unwrap_(PyObject* source); - ~unwrap_(); -}; - -// -// implementations -// -inline unwrap_base::unwrap_base( - PyObject* source, std::pair unwrapper, handle& prev) - : handle(unwrapper.first, prev) - , m_source(source) - , m_data(unwrapper.second) -{ -} - -inline unwrap_base::unwrap_base(PyObject* source, std::pair unwrapper) - : handle(unwrapper.first) - , m_source(source) - , m_data(unwrapper.second) -{ -} - -inline void*& unwrap_base::data() -{ - return m_data; -} - -inline PyObject* unwrap_base::source() const -{ - return m_source; -} - -inline PyObject*& unwrap_base::source() -{ - return m_source; -} - -template -unwrap_more_::unwrap_more_(PyObject* source, handle& prev) - : unwrap_base(source, - registration::unwrapper(source), - prev) -{ -} - -template -unwrap_more_::unwrap_more_(PyObject* source) - : unwrap_base(source, registration::unwrapper(source)) -{ -} - -template -inline unwrap_::unwrap_(PyObject* source) - : unwrap_more_(source) -{ -} - -template -T unwrap_more_::operator*() -{ - return static_cast*>( - get_body())->convert(this->source(), this->data(), boost::type()); -} - -template -unwrap_::~unwrap_() -{ - this->destroy(); -} - -}}} // namespace boost::python::converter - -#endif // UNWRAP_BASE_DWA20011130_HPP diff --git a/include/boost/python/converter/unwrapper.hpp b/include/boost/python/converter/unwrapper.hpp deleted file mode 100644 index 8a16e957..00000000 --- a/include/boost/python/converter/unwrapper.hpp +++ /dev/null @@ -1,40 +0,0 @@ -#error obsolete -// Copyright David Abrahams 2001. 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 UNWRAPPER_DWA2001127_HPP -# define UNWRAPPER_DWA2001127_HPP - -# include -# include -# include -# include - -namespace boost { namespace python { namespace converter { - -template struct unwrap_more_; - -// Abstract base for all unwrappers of Ts -template -struct unwrapper : unwrapper_base -{ - public: - unwrapper(); - - virtual T convert(PyObject*, void*& data, boost::type) const = 0; -}; - -// -// implementations -// -template -unwrapper::unwrapper() - : unwrapper_base(type_id()) -{ -} - -}}} // namespace boost::python::converter - -#endif // UNWRAPPER_DWA2001127_HPP diff --git a/include/boost/python/converter/wrap.hpp b/include/boost/python/converter/wrap.hpp deleted file mode 100644 index b61fff19..00000000 --- a/include/boost/python/converter/wrap.hpp +++ /dev/null @@ -1,167 +0,0 @@ -#error obsolete -// Copyright David Abrahams 2001. 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 WRAP_DWA2001127_HPP -# define WRAP_DWA2001127_HPP -# include -# include -# include -# include -# include -# include -# include -# include - -namespace boost { namespace python { namespace converter { - -extern BOOST_PYTHON_DECL body& identity_wrapper; - -template struct wrapper; - -struct wrap_base : handle -{ - public: // member functions - wrap_base(body*, handle& prev); - wrap_base(body*); - PyObject* release(); - - public: // accessor, really only for wrappers - PyObject*& target() const; - - protected: - void hold_result(PyObject*) const; - - private: - mutable PyObject* m_target; -}; - -template -struct wrap_more_ : wrap_base -{ - protected: - typedef T source_t; - - public: // member functions - wrap_more_(handle& prev); - - PyObject* operator()(source_t) const; - - protected: // constructor for wrap_, below - wrap_more_(); - - private: // helper functions - static wrapper_base* lookup(); - - private: - friend class wrapper; -}; - -template -struct wrap_ : wrap_more_ -{ - typedef typename wrap_more_::source_t source_t; - public: // member functions - wrap_(); - ~wrap_(); -}; - - -// Specialization for PyObject* -template <> -struct wrap_more_ : wrap_base -{ - protected: - typedef PyObject* source_t; - - public: // member functions - wrap_more_(handle& prev) - : wrap_base(&identity_wrapper, prev) {} - - PyObject* operator()(source_t x) const { return x; } - - protected: // constructor for wrap_, below - wrap_more_() - : wrap_base(&identity_wrapper) {} - private: - friend class wrapper; -}; - -// -// implementations -// -inline wrap_base::wrap_base(body* body, handle& prev) - : handle(body, prev) - , m_target(0) -{ -} - -inline wrap_base::wrap_base(body* body) - : handle(body), - m_target(0) -{ -} - -inline PyObject*& wrap_base::target() const -{ - return m_target; -} - -inline void wrap_base::hold_result(PyObject* p) const -{ - assert(m_target == 0); - m_target = p; -} - -inline PyObject* wrap_base::release() -{ - PyObject* result = m_target; - m_target = 0; - return result; -} - -template -inline wrapper_base* wrap_more_::lookup() -{ - // Find the converters registered for T and get a wrapper - // appropriate for the source object - return registration::wrapper(); -} - -template -inline wrap_more_::wrap_more_(handle& prev) - : wrap_base(lookup(), prev) -{ - -} - -template -PyObject* wrap_more_::operator()(source_t x) const -{ - return static_cast*>( - this->get_body())->do_conversion(*this, source_holder(x)); -} - -template -wrap_more_::wrap_more_() - : wrap_base(lookup()) -{ -} - -template -wrap_::wrap_() - : wrap_more_() -{ -} - -template -wrap_::~wrap_() -{ - this->destroy(); -} - -}}} // namespace boost::python::converter - -#endif // WRAP_DWA2001127_HPP diff --git a/include/boost/python/converter/wrapper.hpp b/include/boost/python/converter/wrapper.hpp deleted file mode 100644 index e20ed404..00000000 --- a/include/boost/python/converter/wrapper.hpp +++ /dev/null @@ -1,57 +0,0 @@ -#error obsolete -// Copyright David Abrahams 2001. 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 WRAPPER_DWA2001127_HPP -# define WRAPPER_DWA2001127_HPP -# include -# include -# include -# include -# include - -namespace boost { namespace python { namespace converter { - -extern BOOST_PYTHON_DECL body& identity_wrapper; - -template -struct wrapper : wrapper_base -{ - public: - wrapper(); - - PyObject* do_conversion(wrap_base const&, source_holder_base const&) const; - - // This does the actual conversion - virtual PyObject* convert(T source) const = 0; -}; - -// -// implementations -// - -template -wrapper::wrapper() - : wrapper_base(type_id()) -{ -} - - -template -PyObject* wrapper::do_conversion(wrap_base const& handle_, source_holder_base const& data_) const -{ - // Casting pointers instead of references suppresses a CWPro7 bug. - wrap_more_ const& handle = *static_cast const*>(&handle_); - source_holder const& data = *static_cast const*>(&data_); - if (handle.target() == 0) - { - handle.hold_result(convert(data.value)); - } - return handle.target(); -} - -}}} // namespace boost::python::converter - -#endif // WRAPPER_DWA2001127_HPP diff --git a/include/boost/python/object/auto_ptr_generator.hpp b/include/boost/python/object/auto_ptr_generator.hpp new file mode 100644 index 00000000..9c13e436 --- /dev/null +++ b/include/boost/python/object/auto_ptr_generator.hpp @@ -0,0 +1,23 @@ +// 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 AUTO_PTR_GENERATOR_DWA2002123_HPP +# define AUTO_PTR_GENERATOR_DWA2002123_HPP +# include + +namespace boost { namespace python { namespace object { + +struct auto_ptr_generator +{ + template + struct apply + { + typedef std::auto_ptr type; + }; +}; + +}}} // namespace boost::python::object + +#endif // AUTO_PTR_GENERATOR_DWA2002123_HPP diff --git a/include/boost/python/object/class_unwrapper.hpp b/include/boost/python/object/class_unwrapper.hpp deleted file mode 100644 index 0877ff24..00000000 --- a/include/boost/python/object/class_unwrapper.hpp +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright David Abrahams 2001. 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 CLASS_UNWRAPPER_DWA20011221_HPP -# define CLASS_UNWRAPPER_DWA20011221_HPP - -# include -# include - -namespace boost { namespace python { namespace objects { - -template -struct class_unwrapper -{ - private: - template - struct reference_unwrapper : converter::unwrapper - { - void* can_convert(PyObject* p) const - { - return find_instance(p); - } - - Target convert(PyObject* p, void* data, ) const - { - return *find_instance(p)->target(); - } - }; - - reference_unwrapper m_reference; -# ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - reference_unwrapper m_const_reference; -# endif -}; - -}}} // namespace boost::python::objects - -#endif // CLASS_UNWRAPPER_DWA20011221_HPP diff --git a/include/boost/python/object/pointer_holder.hpp b/include/boost/python/object/pointer_holder.hpp new file mode 100644 index 00000000..81fcac0c --- /dev/null +++ b/include/boost/python/object/pointer_holder.hpp @@ -0,0 +1,201 @@ +// Copyright David Abrahams 2001. 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 POINTER_HOLDER_DWA20011215_HPP +# define POINTER_HOLDER_DWA20011215_HPP + +# include +# include +# include +# include +# include +# include + +namespace boost { namespace python { namespace objects { + +template +struct pointer_holder : instance_holder +{ + pointer_holder(Pointer); + + // Forward construction to the held object + pointer_holder(PyObject*) + : m_p(new Value) {} + + + template + pointer_holder(PyObject*, A1 a1) + : m_p(new Value( + (unwrap_reference::type&)(a1) + )) + {} + + template + pointer_holder(PyObject*, A1 a1, A2 a2) + : m_p(new Value( + (unwrap_reference::type&)(a1) + , (unwrap_reference::type&)(a2) + )) + {} + + template + pointer_holder(PyObject*, A1 a1, A2 a2, A3 a3) + : m_p(new Value( + (unwrap_reference::type&)(a1) + , (unwrap_reference::type&)(a2) + , (unwrap_reference::type&)(a3) + )) + {} + + template + pointer_holder(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4) + : m_p(new Value( + (unwrap_reference::type&)(a1) + , (unwrap_reference::type&)(a2) + , (unwrap_reference::type&)(a3) + , (unwrap_reference::type&)(a4) + )) + {} + + template + pointer_holder(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) + : m_p(new Value( + (unwrap_reference::type&)(a1) + , (unwrap_reference::type&)(a2) + , (unwrap_reference::type&)(a3) + , (unwrap_reference::type&)(a4) + , (unwrap_reference::type&)(a5) + )) {} + + template + pointer_holder(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) + : m_p(new Value( + (unwrap_reference::type&)(a1) + , (unwrap_reference::type&)(a2) + , (unwrap_reference::type&)(a3) + , (unwrap_reference::type&)(a4) + , (unwrap_reference::type&)(a5) + , (unwrap_reference::type&)(a6) + )) {} + + template + pointer_holder(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7) + : m_p(new Value( + (unwrap_reference::type&)(a1) + , (unwrap_reference::type&)(a2) + , (unwrap_reference::type&)(a3) + , (unwrap_reference::type&)(a4) + , (unwrap_reference::type&)(a5) + , (unwrap_reference::type&)(a6) + , (unwrap_reference::type&)(a7) + )) + {} + + template + pointer_holder(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8) + : m_p(new Value( + (unwrap_reference::type&)(a1) + , (unwrap_reference::type&)(a2) + , (unwrap_reference::type&)(a3) + , (unwrap_reference::type&)(a4) + , (unwrap_reference::type&)(a5) + , (unwrap_reference::type&)(a6) + , (unwrap_reference::type&)(a7) + , (unwrap_reference::type&)(a8) + )) + {} + + template + pointer_holder(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9) + : m_p(new Value( + (unwrap_reference::type&)(a1) + , (unwrap_reference::type&)(a2) + , (unwrap_reference::type&)(a3) + , (unwrap_reference::type&)(a4) + , (unwrap_reference::type&)(a5) + , (unwrap_reference::type&)(a6) + , (unwrap_reference::type&)(a7) + , (unwrap_reference::type&)(a8) + , (unwrap_reference::type&)(a9) + )) + {} + + template + pointer_holder(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10) + : m_p(new Value( + (unwrap_reference::type&)(a1) + , (unwrap_reference::type&)(a2) + , (unwrap_reference::type&)(a3) + , (unwrap_reference::type&)(a4) + , (unwrap_reference::type&)(a5) + , (unwrap_reference::type&)(a6) + , (unwrap_reference::type&)(a7) + , (unwrap_reference::type&)(a8) + , (unwrap_reference::type&)(a9) + , (unwrap_reference::type&)(a10) + )) + {} + + private: // required holder implementation + void* holds(converter::type_id_t); + + private: // data members + Pointer m_p; +}; + +}}} + +// back to namespace boost for this forward declaration +namespace boost +{ + template class shared_ptr; +} + +namespace boost { namespace python { namespace objects { + +struct shared_ptr_generator +{ + template + struct apply + { + typedef boost::shared_ptr type; + }; +}; + +// A generator metafunction which can be passed to make_holder +// PointerGenerator should be another generator metafunction which +// makes the appropriate (smart) pointer type to hold the argument to +// pointer_holder_generator. +template +struct pointer_holder_generator +{ + template + struct apply + { + typedef typename detail::eval::type pointer; + typedef pointer_holder type; + }; +}; + +template +pointer_holder::pointer_holder(Pointer p) + : m_p(p) +{ +} + +template +void* pointer_holder::holds(converter::type_id_t dst_t) +{ + if (dst_t == converter::type_id()) + return &this->m_p; + + converter::type_id_t src_t = converter::type_id(); + return src_t == dst_t ? &*this->m_p + : find_dynamic_type(&*this->m_p, src_t, dst_t); +} + +}}} // namespace boost::python::objects + +#endif // POINTER_HOLDER_DWA20011215_HPP diff --git a/include/boost/python/reference_from_python.hpp b/include/boost/python/reference_from_python.hpp index 8e7b9b6c..a9631dc5 100644 --- a/include/boost/python/reference_from_python.hpp +++ b/include/boost/python/reference_from_python.hpp @@ -26,23 +26,28 @@ template < PyTypeObject const* python_type , class Value , class PythonObject - , Value& (*extract)(PythonObject&) + , class Extract > -struct reference_from_python : type_from_python +struct reference_from_python { + typedef type_from_python convertible_t; + reference_from_python() - : m_mutable_converter(convertible, convert_mutable) - , m_const_converter(convertible, convert_const) + : m_mutable_converter( + &convertible_t::convertible, convert_mutable) + + , m_const_converter( + &convertible_t::convertible, convert_const) {} static Value& convert_mutable(PyObject* op, converter::from_python_data&) { - return extract(*(PythonObject*)op); + return Extract::execute(*(PythonObject*)op); } static Value const& convert_const(PyObject* op, converter::from_python_data&) { - return extract(*(PythonObject*)op); + return Extract::execute(*(PythonObject*)op); } private: diff --git a/include/boost/python/value_from_python.hpp b/include/boost/python/value_from_python.hpp index bb4ecf87..0ff80323 100644 --- a/include/boost/python/value_from_python.hpp +++ b/include/boost/python/value_from_python.hpp @@ -9,12 +9,27 @@ # include # include # include +# include namespace boost { namespace python { template struct value_from_python { + typedef converter::from_python_check from_python_check; + + value_from_python(from_python_check convertible) + : m_converter( + convertible + , &Derived::convert + + // Change this to a compile-time check later to avoid + // generating destroy function + , has_trivial_destructor::value ? 0 : &Derived::destroy + ) + { + } + value_from_python() : m_converter( &Derived::convertible @@ -25,9 +40,6 @@ struct value_from_python , has_trivial_destructor::value ? 0 : &Derived::destroy ) { - // Scalar types are really converted by-value; the formulation - // is much simpler. - BOOST_STATIC_ASSERT(!(is_scalar::value)); } static void* get_storage(converter::from_python_data& data) diff --git a/src/converter/builtin_converters.cpp b/src/converter/builtin_converters.cpp index 07a00259..c2ce3dae 100644 --- a/src/converter/builtin_converters.cpp +++ b/src/converter/builtin_converters.cpp @@ -8,7 +8,8 @@ #include #include #include -#include +#include +#include #include #include //#include @@ -18,113 +19,185 @@ namespace boost { namespace python { namespace converter { namespace { - struct int_value_functions_base + // Only an object which we know is holding a char const* can be + // converted to one + struct convertible_to_cstring { - static void* convertible(PyObject* obj) + static unaryfunc* execute(PyObject* obj) { - PyNumberMethods* number_methods = obj->ob_type->tp_as_number; - - return number_methods && number_methods->nb_int - ? &number_methods->nb_int : 0; - } - }; - - template - struct int_value_functions : int_value_functions_base - { - static T convert(PyObject* obj, from_python_data& data) - { - unaryfunc f = *static_cast(data.stage1); - ref int_object(f(obj)); - return numeric_cast(PyInt_AsLong(int_object.get())); + return PyString_Check(obj) ? &obj->ob_type->tp_str : 0; } }; - struct cstring_value_functions + struct extract_cstring { - static void* convertible(PyObject* obj) - { - return PyString_Check(obj) ? obj : 0; - } - - static char const* convert(PyObject* obj, from_python_data&) + static char const* execute(PyObject* obj) { return PyString_AsString(obj); } }; - char constructed; - - struct string_cref_functions + // Any object which can be converted to a Python string can also be + // converted to a C++ string, since the latter owns its bytes. + struct convertible_to_string { - typedef std::string const& result_type; - - static void* convertible(PyObject* obj) + static unaryfunc* execute(PyObject* obj) { return obj->ob_type->tp_str ? &obj->ob_type->tp_str : 0; } + }; + + // Transform a function returning a unaryfunc* into one that returns a void* + template + struct return_void_ptr + { + static void* execute(PyObject* p) { return F::execute(p); } + }; + + template < + class T // The target type + , class Convertible // returns a pointer to a unaryfunc producing an object + , class TExtract // ...from which TExtract extracts T's constructor argument + > + struct tp_scalar_from_python + : from_python_converter + { + private: + typedef return_void_ptr convertible_fn; - static std::string const& convert( - PyObject* obj, from_python_data& data) + public: + tp_scalar_from_python() + : from_python_converter( + &convertible_fn::execute + , convert) + {} + + static T convert(PyObject* obj, from_python_data& data) { - ref string_object((**static_cast(data.stage1))(obj)); - void* storage = get_storage(data); - std::string* p = new (storage) std::string(PyString_AsString(string_object.get())); + unaryfunc converter = *(unaryfunc*)data.stage1; + ref converted(converter(obj)); + return TExtract::execute(converted.get()); + } + }; + + // Extract a reference to T using the functions in the source + // object's type slots + template < + class T // The target type + , class Convertible // returns a pointer to a unaryfunc producing an object + , class TExtract // ...from which TExtract extracts T's constructor argument + > + struct tp_cref_from_python + : value_from_python > + { + private: + typedef value_from_python > base; + + public: + tp_cref_from_python() + : base(&return_void_ptr::execute) + {} + + static T const& convert(PyObject* obj, from_python_data& data) + { + unaryfunc converter = *(unaryfunc*)data.stage1; + + void* storage = get_storage(data); + + ref converted(converter(obj)); + + T* const p = new (storage) T(TExtract::execute(converted.get())); // note that construction is successful. - data.stage1 = &constructed; + data.stage1 = p; + return *p; } + }; - static void destroy(from_python_data& data) + struct convertible_to_int + { + static unaryfunc* execute(PyObject* obj) { - if (data.stage1 == &constructed) + PyNumberMethods* number_methods = obj->ob_type->tp_as_number; + if (number_methods == 0) + return 0; + + // For floating types, return the float conversion slot to avoid + // creating a new object. We'll handle that in + // py_int_or_float_as_long, below + if (PyObject_TypeCheck(obj, &PyFloat_Type) && number_methods->nb_float) + return &number_methods->nb_float; + + return number_methods && number_methods->nb_int + ? &number_methods->nb_int : 0; + } + }; + + struct py_int_or_float_as_long + { + static long execute(PyObject* obj) + { + if (PyObject_TypeCheck(obj, &PyFloat_Type)) { - typedef std::string string_t; - void* storage = get_storage(data); - ((string_t*)storage)->~string_t(); + return numeric_cast(PyFloat_AS_DOUBLE(obj)); + } + else + { + return PyInt_AS_LONG(obj); } } }; - template - struct rvalue_const_ref_functions : Base + struct convertible_to_double { - static T const& convert(PyObject* obj, from_python_data& data) + static unaryfunc* execute(PyObject* obj) { - void* storage = get_storage(data); - T* p = new (storage) T(Base::convert(obj,data)); - - // note that construction is successful. - data.stage1 = &constructed; - return *p; + PyNumberMethods* number_methods = obj->ob_type->tp_as_number; + if (number_methods == 0) + return 0; + + // For integer types, return the tp_int conversion slot to avoid + // creating a new object. We'll handle that in + // py_float_or_int_as_double, below + if (PyObject_TypeCheck(obj, &PyInt_Type) && number_methods->nb_int) + return &number_methods->nb_int; + + return number_methods && number_methods->nb_float + ? &number_methods->nb_float : 0; } }; - struct register_int_converters + struct py_float_or_int_as_double { - template - struct apply + static double execute(PyObject* obj) { - typedef void type; - - static void execute() + if (PyObject_TypeCheck(obj, &PyInt_Type)) { - typedef int_value_functions value_functions; - typedef rvalue_const_ref_functions cref_functions; - - static from_python_converter value_from_python( - value_functions::convertible - , value_functions::convert); - static from_python_converter cref_from_python( - cref_functions::convertible - , cref_functions::convert); - }; - }; + return PyInt_AS_LONG(obj); + } + else + { + return PyFloat_AS_DOUBLE(obj); + } + } }; -} -#define REGISTER_INT_CONVERTERS(U) register_int_converters::apply::execute() + template + struct scalar_from_python + { + tp_cref_from_python cref_converter; + tp_scalar_from_python value_converter; + }; + + template + void register_int_converters(T* = 0) + { + static scalar_from_python x; + }; +} + +#define REGISTER_INT_CONVERTERS(U) register_int_converters() #define REGISTER_INT_CONVERTERS2(U) REGISTER_INT_CONVERTERS(signed U); REGISTER_INT_CONVERTERS(unsigned U) @@ -134,20 +207,21 @@ void initialize_builtin_converters() REGISTER_INT_CONVERTERS2(short); REGISTER_INT_CONVERTERS2(int); REGISTER_INT_CONVERTERS2(long); -// mpl::for_each::execute(); - static from_python_converter cstring_from_python( - &cstring_value_functions::convertible - , &cstring_value_functions::convert); + static scalar_from_python< + float,convertible_to_double,py_float_or_int_as_double> float_from_python; + + static scalar_from_python< + double,convertible_to_double,py_float_or_int_as_double> double_from_python; + + static scalar_from_python< + long double,convertible_to_double,py_float_or_int_as_double> long_double_from_python; + + static scalar_from_python< + char const*, convertible_to_cstring, extract_cstring> cstring_from_python; - static from_python_converter cstring_cref_from_python( - &rvalue_const_ref_functions::convertible - , &rvalue_const_ref_functions::convert); - - static from_python_converter string_cref_from_python( - &string_cref_functions::convertible - , &string_cref_functions::convert - , &string_cref_functions::destroy); + static tp_cref_from_python< + std::string, convertible_to_string, extract_cstring> string_from_python; } }}} // namespace boost::python::converter diff --git a/src/converter/from_python.cpp b/src/converter/from_python.cpp new file mode 100644 index 00000000..979ad935 --- /dev/null +++ b/src/converter/from_python.cpp @@ -0,0 +1,27 @@ +// 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 + +namespace boost { namespace python { namespace converter { + +from_python_converter_base::from_python_converter_base( + type_id_t type + , from_python_check checker + ) + : body(type) + , m_convertible(checker) +{ + registry::insert(*this); +} + +from_python_converter_base::~from_python_converter_base() +{ + if (can_unregister()) + registry::remove(*this); +} + +}}} // namespace boost::python::converter diff --git a/src/converter/to_python.cpp b/src/converter/to_python.cpp new file mode 100644 index 00000000..9cede51d --- /dev/null +++ b/src/converter/to_python.cpp @@ -0,0 +1,24 @@ +// 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 + +namespace boost { namespace python { namespace converter { + +to_python_converter_base::to_python_converter_base(type_id_t key, to_python_function_base convert) + : body(key) + , m_convert(convert) +{ + registry::insert(*this); +} + +to_python_converter_base::~to_python_converter_base() +{ + registry::remove(*this); +} + +}}} // namespace boost::python::converter diff --git a/test/m1.cpp b/test/m1.cpp index 6b4c55e1..d422b426 100644 --- a/test/m1.cpp +++ b/test/m1.cpp @@ -64,8 +64,11 @@ struct SimpleObject { PyObject_HEAD simple x; +}; - static simple& extract(SimpleObject& o) { return o.x; } +struct extract_simple_object +{ + static simple& execute(SimpleObject& o) { return o.x; } }; PyTypeObject SimpleType = { @@ -209,12 +212,13 @@ BOOST_PYTHON_MODULE_INIT(m1) &SimpleType , simple , SimpleObject - , &SimpleObject::extract + , extract_simple_object > unwrap_simple; static to_python_converter simple_ref_wrapper(simple_ref_to_python); + module m1("m1"); typedef boost::python::objects::pointer_holder_generator< diff --git a/test/m2.cpp b/test/m2.cpp index be2934e0..0a5df161 100644 --- a/test/m2.cpp +++ b/test/m2.cpp @@ -49,9 +49,6 @@ PyObject* unwrap_int_const_ref(int const& x) return PyInt_FromLong(x); } -// MSVC6 bug workaround -template struct xxxx; - // rewrap extracts a T from the argument, then converts the T back // to a PyObject* and returns it. template diff --git a/test/test_builtin_converters.cpp b/test/test_builtin_converters.cpp new file mode 100644 index 00000000..6ffccdf9 --- /dev/null +++ b/test/test_builtin_converters.cpp @@ -0,0 +1,65 @@ +// 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 + + +template +struct by_value +{ + static T rewrap(T x) + { + return x; + } +}; + +template +struct by_const_reference +{ + static T rewrap(T const& x) + { + return x; + } +}; + +BOOST_PYTHON_MODULE_INIT(builtin_converters_ext) +{ + boost::python::module("builtin_converters_ext") + + .def("rewrap_value_signed_char", by_value::rewrap) + .def("rewrap_value_unsigned_char", by_value::rewrap) + .def("rewrap_value_int", by_value::rewrap) + .def("rewrap_value_unsigned_int", by_value::rewrap) + .def("rewrap_value_short", by_value::rewrap) + .def("rewrap_value_unsigned_short", by_value::rewrap) + .def("rewrap_value_long", by_value::rewrap) + .def("rewrap_value_unsigned_long", by_value::rewrap) + .def("rewrap_value_float", by_value::rewrap) + .def("rewrap_value_double", by_value::rewrap) + .def("rewrap_value_long_double", by_value::rewrap) + .def("rewrap_value_string", by_value::rewrap) + .def("rewrap_value_cstring", by_value::rewrap) + + + .def("rewrap_const_reference_signed_char", by_const_reference::rewrap) + .def("rewrap_const_reference_unsigned_char", by_const_reference::rewrap) + .def("rewrap_const_reference_int", by_const_reference::rewrap) + .def("rewrap_const_reference_unsigned_int", by_const_reference::rewrap) + .def("rewrap_const_reference_short", by_const_reference::rewrap) + .def("rewrap_const_reference_unsigned_short", by_const_reference::rewrap) + .def("rewrap_const_reference_long", by_const_reference::rewrap) + .def("rewrap_const_reference_unsigned_long", by_const_reference::rewrap) + .def("rewrap_const_reference_float", by_const_reference::rewrap) + .def("rewrap_const_reference_double", by_const_reference::rewrap) + .def("rewrap_const_reference_long_double", by_const_reference::rewrap) + .def("rewrap_const_reference_string", by_const_reference::rewrap) + .def("rewrap_const_reference_cstring", by_const_reference::rewrap) + + ; +} + diff --git a/test/test_builtin_converters.py b/test/test_builtin_converters.py new file mode 100644 index 00000000..3941a29c --- /dev/null +++ b/test/test_builtin_converters.py @@ -0,0 +1,86 @@ +""" +>>> from builtin_converters_ext import * +>>> rewrap_value_signed_char(42) +42 +>>> rewrap_value_unsigned_char(42) +42 +>>> rewrap_value_int(42) +42 +>>> rewrap_value_unsigned_int(42) +42 +>>> rewrap_value_short(42) +42 +>>> rewrap_value_unsigned_short(42) +42 +>>> rewrap_value_long(42) +42 +>>> rewrap_value_unsigned_long(42) +42 + +>>> abs(rewrap_value_float(4.2) - 4.2) < .000001 +1 +>>> rewrap_value_double(4.2) - 4.2 +0.0 +>>> rewrap_value_long_double(4.2) - 4.2 +0.0 + +>>> rewrap_value_cstring('hello, world') +'hello, world' +>>> rewrap_value_string('yo, wassup?') +'yo, wassup?' + +>>> rewrap_const_reference_signed_char(42) +42 +>>> rewrap_const_reference_unsigned_char(42) +42 +>>> rewrap_const_reference_int(42) +42 +>>> rewrap_const_reference_unsigned_int(42) +42 +>>> rewrap_const_reference_short(42) +42 +>>> rewrap_const_reference_unsigned_short(42) +42 +>>> rewrap_const_reference_long(42) +42 +>>> rewrap_const_reference_unsigned_long(42) +42 +>>> abs(rewrap_const_reference_float(4.2) - 4.2) < .000001 +1 +>>> rewrap_const_reference_double(4.2) - 4.2 +0.0 +>>> rewrap_const_reference_long_double(4.2) - 4.2 +0.0 + +>>> rewrap_const_reference_cstring('hello, world') +'hello, world' +>>> rewrap_const_reference_string('yo, wassup?') +'yo, wassup?' + +Now check implicit conversions between floating/integer types + +>>> rewrap_const_reference_float(42) +42.0 + +>>> rewrap_const_reference_int(42.0) +42 + +>>> rewrap_value_float(42) +42.0 + +>>> rewrap_value_int(42.0) +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])