diff options
author | Anas Nashif <anas.nashif@intel.com> | 2012-10-30 12:57:26 -0700 |
---|---|---|
committer | Anas Nashif <anas.nashif@intel.com> | 2012-10-30 12:57:26 -0700 |
commit | 1a78a62555be32868418fe52f8e330c9d0f95d5a (patch) | |
tree | d3765a80e7d3b9640ec2e930743630cd6b9fce2b /boost/python | |
download | boost-1a78a62555be32868418fe52f8e330c9d0f95d5a.tar.gz boost-1a78a62555be32868418fe52f8e330c9d0f95d5a.tar.bz2 boost-1a78a62555be32868418fe52f8e330c9d0f95d5a.zip |
Imported Upstream version 1.49.0upstream/1.49.0
Diffstat (limited to 'boost/python')
210 files changed, 21001 insertions, 0 deletions
diff --git a/boost/python/arg_from_python.hpp b/boost/python/arg_from_python.hpp new file mode 100644 index 0000000000..05611edbbd --- /dev/null +++ b/boost/python/arg_from_python.hpp @@ -0,0 +1,76 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef ARG_FROM_PYTHON_DWA2002128_HPP +# define ARG_FROM_PYTHON_DWA2002128_HPP + +# include <boost/python/detail/prefix.hpp> +# include <boost/python/converter/arg_from_python.hpp> +# if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1400)) \ + || BOOST_WORKAROUND(BOOST_INTEL_WIN, BOOST_TESTED_AT(800)) +# include <boost/type_traits/remove_cv.hpp> +#endif + +namespace boost { namespace python { + +template <class T> +struct arg_from_python + : converter::select_arg_from_python< +# if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1400)) \ + || BOOST_WORKAROUND(BOOST_INTEL_WIN, BOOST_TESTED_AT(800)) + typename boost::remove_cv<T>::type +# else + T +# endif + >::type +{ + typedef typename converter::select_arg_from_python< +# if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1400)) \ + || BOOST_WORKAROUND(BOOST_INTEL_WIN, BOOST_TESTED_AT(800)) + typename boost::remove_cv<T>::type +# else + T +# endif + >::type base; + + arg_from_python(PyObject*); +}; + +// specialization for PyObject* +template <> +struct arg_from_python<PyObject*> +{ + typedef PyObject* result_type; + + arg_from_python(PyObject* p) : m_source(p) {} + bool convertible() const { return true; } + PyObject* operator()() const { return m_source; } + private: + PyObject* m_source; +}; + +template <> +struct arg_from_python<PyObject* const&> +{ + typedef PyObject* const& result_type; + + arg_from_python(PyObject* p) : m_source(p) {} + bool convertible() const { return true; } + PyObject*const& operator()() const { return m_source; } + private: + PyObject* m_source; +}; + +// +// implementations +// +template <class T> +inline arg_from_python<T>::arg_from_python(PyObject* source) + : base(source) +{ +} + +}} // namespace boost::python + +#endif // ARG_FROM_PYTHON_DWA2002128_HPP diff --git a/boost/python/args.hpp b/boost/python/args.hpp new file mode 100644 index 0000000000..8f8791d76f --- /dev/null +++ b/boost/python/args.hpp @@ -0,0 +1,175 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef KEYWORDS_DWA2002323_HPP +# define KEYWORDS_DWA2002323_HPP + +# include <boost/python/detail/prefix.hpp> + +# include <boost/python/args_fwd.hpp> +# include <boost/config.hpp> +# include <boost/python/detail/preprocessor.hpp> +# include <boost/python/detail/type_list.hpp> + +# include <boost/type_traits/is_reference.hpp> +# include <boost/type_traits/remove_reference.hpp> +# include <boost/type_traits/remove_cv.hpp> + +# include <boost/preprocessor/enum_params.hpp> +# include <boost/preprocessor/repeat.hpp> +# include <boost/preprocessor/facilities/intercept.hpp> +# include <boost/preprocessor/iteration/local.hpp> + +# include <boost/python/detail/mpl_lambda.hpp> +# include <boost/python/object_core.hpp> + +# include <boost/mpl/bool.hpp> + +# include <cstddef> +# include <algorithm> + +namespace boost { namespace python { + +typedef detail::keywords<1> arg; +typedef arg arg_; // gcc 2.96 workaround + +namespace detail +{ + template <std::size_t nkeywords> + struct keywords_base + { + BOOST_STATIC_CONSTANT(std::size_t, size = nkeywords); + + keyword_range range() const + { + return keyword_range(elements, elements + nkeywords); + } + + keyword elements[nkeywords]; + + keywords<nkeywords+1> + operator,(python::arg const &k) const; + + keywords<nkeywords + 1> + operator,(char const *name) const; + }; + + template <std::size_t nkeywords> + struct keywords : keywords_base<nkeywords> + { + }; + + template <> + struct keywords<1> : keywords_base<1> + { + explicit keywords(char const *name) + { + elements[0].name = name; + } + + template <class T> + python::arg& operator=(T const& value) + { + object z(value); + elements[0].default_value = handle<>(python::borrowed(object(value).ptr())); + return *this; + } + + operator detail::keyword const&() const + { + return elements[0]; + } + }; + + template <std::size_t nkeywords> + inline + keywords<nkeywords+1> + keywords_base<nkeywords>::operator,(python::arg const &k) const + { + keywords<nkeywords> const& l = *static_cast<keywords<nkeywords> const*>(this); + python::detail::keywords<nkeywords+1> res; + std::copy(l.elements, l.elements+nkeywords, res.elements); + res.elements[nkeywords] = k.elements[0]; + return res; + } + + template <std::size_t nkeywords> + inline + keywords<nkeywords + 1> + keywords_base<nkeywords>::operator,(char const *name) const + { + return this->operator,(python::arg(name)); + } + +# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + template<typename T> + struct is_keywords + { + BOOST_STATIC_CONSTANT(bool, value = false); + }; + + template<std::size_t nkeywords> + struct is_keywords<keywords<nkeywords> > + { + BOOST_STATIC_CONSTANT(bool, value = true); + }; + template <class T> + struct is_reference_to_keywords + { + BOOST_STATIC_CONSTANT(bool, is_ref = is_reference<T>::value); + typedef typename remove_reference<T>::type deref; + typedef typename remove_cv<deref>::type key_t; + BOOST_STATIC_CONSTANT(bool, is_key = is_keywords<key_t>::value); + BOOST_STATIC_CONSTANT(bool, value = (is_ref & is_key)); + + typedef mpl::bool_<value> type; + BOOST_PYTHON_MPL_LAMBDA_SUPPORT(1,is_reference_to_keywords,(T)) + }; +# else + typedef char (&yes_keywords_t)[1]; + typedef char (&no_keywords_t)[2]; + + no_keywords_t is_keywords_test(...); + + template<std::size_t nkeywords> + yes_keywords_t is_keywords_test(void (*)(keywords<nkeywords>&)); + + template<std::size_t nkeywords> + yes_keywords_t is_keywords_test(void (*)(keywords<nkeywords> const&)); + + template<typename T> + class is_reference_to_keywords + { + public: + BOOST_STATIC_CONSTANT( + bool, value = ( + sizeof(detail::is_keywords_test( (void (*)(T))0 )) + == sizeof(detail::yes_keywords_t))); + + typedef mpl::bool_<value> type; + BOOST_PYTHON_MPL_LAMBDA_SUPPORT(1,is_reference_to_keywords,(T)) + }; +# endif +} + +inline detail::keywords<1> args(char const* name) +{ + return detail::keywords<1>(name); +} + +# define BOOST_PYTHON_ASSIGN_NAME(z, n, _) result.elements[n].name = name##n; +# define BOOST_PP_LOCAL_MACRO(n) \ +inline detail::keywords<n> args(BOOST_PP_ENUM_PARAMS_Z(1, n, char const* name)) \ +{ \ + detail::keywords<n> result; \ + BOOST_PP_REPEAT_1(n, BOOST_PYTHON_ASSIGN_NAME, _) \ + return result; \ +} +# define BOOST_PP_LOCAL_LIMITS (2, BOOST_PYTHON_MAX_ARITY) +# include BOOST_PP_LOCAL_ITERATE() + +}} // namespace boost::python + + +# endif // KEYWORDS_DWA2002323_HPP diff --git a/boost/python/args_fwd.hpp b/boost/python/args_fwd.hpp new file mode 100644 index 0000000000..39239461b0 --- /dev/null +++ b/boost/python/args_fwd.hpp @@ -0,0 +1,52 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef ARGS_FWD_DWA2002927_HPP +# define ARGS_FWD_DWA2002927_HPP + +# include <boost/python/detail/prefix.hpp> + +# include <boost/python/handle.hpp> +# include <boost/config.hpp> +# include <cstddef> +# include <utility> + +namespace boost { namespace python { + +namespace detail +{ + struct keyword + { + keyword(char const* name_=0) + : name(name_) + {} + + char const* name; + handle<> default_value; + }; + + template <std::size_t nkeywords = 0> struct keywords; + + typedef std::pair<keyword const*, keyword const*> keyword_range; + + template <> + struct keywords<0> + { + BOOST_STATIC_CONSTANT(std::size_t, size = 0); + static keyword_range range() { return keyword_range(); } + }; + + namespace error + { + template <int keywords, int function_args> + struct more_keywords_than_function_arguments + { + typedef char too_many_keywords[keywords > function_args ? -1 : 1]; + }; + } +} + +}} // namespace boost::python + +#endif // ARGS_FWD_DWA2002927_HPP diff --git a/boost/python/back_reference.hpp b/boost/python/back_reference.hpp new file mode 100644 index 0000000000..c1daba60c1 --- /dev/null +++ b/boost/python/back_reference.hpp @@ -0,0 +1,102 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef BACK_REFERENCE_DWA2002510_HPP +# define BACK_REFERENCE_DWA2002510_HPP + +# include <boost/python/detail/prefix.hpp> + +# include <boost/python/object_fwd.hpp> +# include <boost/python/detail/dependent.hpp> +# include <boost/python/detail/raw_pyobject.hpp> + +namespace boost { namespace python { + +template <class T> +struct back_reference +{ + private: // types + typedef typename detail::dependent<object,T>::type source_t; + public: + typedef T type; + + back_reference(PyObject*, T); + source_t const& source() const; + T get() const; + private: + source_t m_source; + T m_value; +}; + +# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +template<typename T> +class is_back_reference +{ + public: + BOOST_STATIC_CONSTANT(bool, value = false); +}; + +template<typename T> +class is_back_reference<back_reference<T> > +{ + public: + BOOST_STATIC_CONSTANT(bool, value = true); +}; + +# else // no partial specialization + +}} // namespace boost::python + +#include <boost/type.hpp> + +namespace boost { namespace python { + +namespace detail +{ + typedef char (&yes_back_reference_t)[1]; + typedef char (&no_back_reference_t)[2]; + + no_back_reference_t is_back_reference_test(...); + + template<typename T> + yes_back_reference_t is_back_reference_test(boost::type< back_reference<T> >); +} + +template<typename T> +class is_back_reference +{ + public: + BOOST_STATIC_CONSTANT( + bool, value = ( + sizeof(detail::is_back_reference_test(boost::type<T>())) + == sizeof(detail::yes_back_reference_t))); +}; + +# endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + +// +// implementations +// +template <class T> +back_reference<T>::back_reference(PyObject* p, T x) + : m_source(detail::borrowed_reference(p)) + , m_value(x) +{ +} + +template <class T> +typename back_reference<T>::source_t const& back_reference<T>::source() const +{ + return m_source; +} + +template <class T> +T back_reference<T>::get() const +{ + return m_value; +} + +}} // namespace boost::python + +#endif // BACK_REFERENCE_DWA2002510_HPP diff --git a/boost/python/base_type_traits.hpp b/boost/python/base_type_traits.hpp new file mode 100644 index 0000000000..e1c6a4843f --- /dev/null +++ b/boost/python/base_type_traits.hpp @@ -0,0 +1,43 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef BASE_TYPE_TRAITS_DWA2002614_HPP +# define BASE_TYPE_TRAITS_DWA2002614_HPP + +# include <boost/python/detail/prefix.hpp> + +namespace boost { namespace python { + +namespace detail +{ + struct unspecialized {}; +} + +// Derive from unspecialized so we can detect whether traits are +// specialized +template <class T> struct base_type_traits + : detail::unspecialized +{}; + +template <> +struct base_type_traits<PyObject> +{ + typedef PyObject type; +}; + +template <> +struct base_type_traits<PyTypeObject> +{ + typedef PyObject type; +}; + +template <> +struct base_type_traits<PyMethodObject> +{ + typedef PyObject type; +}; + +}} // namespace boost::python + +#endif // BASE_TYPE_TRAITS_DWA2002614_HPP diff --git a/boost/python/bases.hpp b/boost/python/bases.hpp new file mode 100644 index 0000000000..0bd7350e55 --- /dev/null +++ b/boost/python/bases.hpp @@ -0,0 +1,68 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef BASES_DWA2002321_HPP +# define BASES_DWA2002321_HPP + +# include <boost/python/detail/prefix.hpp> +# include <boost/type_traits/object_traits.hpp> +# include <boost/python/detail/type_list.hpp> +# include <boost/mpl/if.hpp> +# include <boost/mpl/bool.hpp> +# include <boost/preprocessor/enum_params_with_a_default.hpp> +# include <boost/preprocessor/enum_params.hpp> + +namespace boost { namespace python { + +# define BOOST_PYTHON_BASE_PARAMS BOOST_PP_ENUM_PARAMS_Z(1, BOOST_PYTHON_MAX_BASES, Base) + + // A type list for specifying bases + template < BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT(BOOST_PYTHON_MAX_BASES, typename Base, mpl::void_) > + struct bases : detail::type_list< BOOST_PYTHON_BASE_PARAMS >::type + {}; + + namespace detail + { +# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + template <class T> struct specifies_bases + : mpl::false_ + { + }; + + template < BOOST_PP_ENUM_PARAMS_Z(1, BOOST_PYTHON_MAX_BASES, class Base) > + struct specifies_bases< bases< BOOST_PYTHON_BASE_PARAMS > > + : mpl::true_ + { + }; +# else + template < BOOST_PP_ENUM_PARAMS(BOOST_PYTHON_MAX_BASES, class Base) > + static char is_bases_helper(bases< BOOST_PYTHON_BASE_PARAMS > const&); + + static char (& is_bases_helper(...) )[256]; + + template <class T> + struct specifies_bases + { + private: + static typename add_reference<T>::type make(); + BOOST_STATIC_CONSTANT(bool, non_ref = !is_reference<T>::value); + public: + BOOST_STATIC_CONSTANT(bool, value = non_ref & (sizeof(is_bases_helper(make())) == 1)); + typedef mpl::bool_<value> type; + }; +# endif + template <class T, class Prev = bases<> > + struct select_bases + : mpl::if_< + specifies_bases<T> + , T + , Prev + > + { + }; + } +# undef BOOST_PYTHON_BASE_PARAMS +}} // namespace boost::python + +#endif // BASES_DWA2002321_HPP diff --git a/boost/python/borrowed.hpp b/boost/python/borrowed.hpp new file mode 100644 index 0000000000..fd2716bfbd --- /dev/null +++ b/boost/python/borrowed.hpp @@ -0,0 +1,21 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef BORROWED_DWA2002614_HPP +# define BORROWED_DWA2002614_HPP + +# include <boost/python/detail/prefix.hpp> +# include <boost/python/detail/borrowed_ptr.hpp> + +namespace boost { namespace python { + +template <class T> +inline python::detail::borrowed<T>* borrowed(T* p) +{ + return (detail::borrowed<T>*)p; +} + +}} // namespace boost::python + +#endif // BORROWED_DWA2002614_HPP diff --git a/boost/python/call.hpp b/boost/python/call.hpp new file mode 100644 index 0000000000..5d2d7d2341 --- /dev/null +++ b/boost/python/call.hpp @@ -0,0 +1,83 @@ +#if !defined(BOOST_PP_IS_ITERATING) + +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +# ifndef CALL_DWA2002411_HPP +# define CALL_DWA2002411_HPP + +# include <boost/python/detail/prefix.hpp> + +# include <boost/type.hpp> + +# include <boost/python/converter/arg_to_python.hpp> +# include <boost/python/converter/return_from_python.hpp> +# include <boost/python/detail/preprocessor.hpp> +# include <boost/python/detail/void_return.hpp> + +# include <boost/preprocessor/comma_if.hpp> +# include <boost/preprocessor/iterate.hpp> +# include <boost/preprocessor/repeat.hpp> +# include <boost/preprocessor/debug/line.hpp> +# include <boost/preprocessor/repetition/enum_trailing_params.hpp> +# include <boost/preprocessor/repetition/enum_binary_params.hpp> + +namespace boost { namespace python { + +# define BOOST_PYTHON_FAST_ARG_TO_PYTHON_GET(z, n, _) \ + , converter::arg_to_python<A##n>(a##n).get() + +# define BOOST_PP_ITERATION_PARAMS_1 (3, (0, BOOST_PYTHON_MAX_ARITY, <boost/python/call.hpp>)) +# include BOOST_PP_ITERATE() + +# undef BOOST_PYTHON_FAST_ARG_TO_PYTHON_GET + +}} // namespace boost::python + +# endif // CALL_DWA2002411_HPP + +// For gcc 4.4 compatability, we must include the +// BOOST_PP_ITERATION_DEPTH test inside an #else clause. +#else // BOOST_PP_IS_ITERATING +#if BOOST_PP_ITERATION_DEPTH() == 1 +# if !(BOOST_WORKAROUND(__MWERKS__, > 0x3100) \ + && BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3201))) +# line BOOST_PP_LINE(__LINE__, call.hpp) +# endif + +# define N BOOST_PP_ITERATION() + +template < + class R + BOOST_PP_ENUM_TRAILING_PARAMS_Z(1, N, class A) + > +typename detail::returnable<R>::type +call(PyObject* callable + BOOST_PP_COMMA_IF(N) BOOST_PP_ENUM_BINARY_PARAMS_Z(1, N, A, const& a) + , boost::type<R>* = 0 + ) +{ + PyObject* const result = + PyEval_CallFunction( + callable + , const_cast<char*>("(" BOOST_PP_REPEAT_1ST(N, BOOST_PYTHON_FIXED, "O") ")") + BOOST_PP_REPEAT_1ST(N, BOOST_PYTHON_FAST_ARG_TO_PYTHON_GET, nil) + ); + + // This conversion *must not* be done in the same expression as + // the call, because, in the special case where the result is a + // reference a Python object which was created by converting a C++ + // argument for passing to PyEval_CallFunction, its reference + // count will be 2 until the end of the full expression containing + // the conversion, and that interferes with dangling + // pointer/reference detection. + converter::return_from_python<R> converter; + return converter(result); +} + +# undef N + +#endif // BOOST_PP_ITERATION_DEPTH() +#endif diff --git a/boost/python/call_method.hpp b/boost/python/call_method.hpp new file mode 100644 index 0000000000..410f66820e --- /dev/null +++ b/boost/python/call_method.hpp @@ -0,0 +1,83 @@ +#if !defined(BOOST_PP_IS_ITERATING) + +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +# ifndef CALL_METHOD_DWA2002411_HPP +# define CALL_METHOD_DWA2002411_HPP + +# include <boost/python/detail/prefix.hpp> + +# include <boost/type.hpp> + +# include <boost/python/converter/arg_to_python.hpp> +# include <boost/python/converter/return_from_python.hpp> +# include <boost/python/detail/preprocessor.hpp> +# include <boost/python/detail/void_return.hpp> + +# include <boost/preprocessor/comma_if.hpp> +# include <boost/preprocessor/iterate.hpp> +# include <boost/preprocessor/repeat.hpp> +# include <boost/preprocessor/debug/line.hpp> +# include <boost/preprocessor/repetition/enum_trailing_params.hpp> +# include <boost/preprocessor/repetition/enum_binary_params.hpp> + +namespace boost { namespace python { + +# define BOOST_PYTHON_FAST_ARG_TO_PYTHON_GET(z, n, _) \ + , converter::arg_to_python<A##n>(a##n).get() + +# define BOOST_PP_ITERATION_PARAMS_1 (3, (0, BOOST_PYTHON_MAX_ARITY, <boost/python/call_method.hpp>)) +# include BOOST_PP_ITERATE() + +# undef BOOST_PYTHON_FAST_ARG_TO_PYTHON_GET + +}} // namespace boost::python + +# endif // CALL_METHOD_DWA2002411_HPP + +// For gcc 4.4 compatability, we must include the +// BOOST_PP_ITERATION_DEPTH test inside an #else clause. +#else // BOOST_PP_IS_ITERATING +#if BOOST_PP_ITERATION_DEPTH() == 1 +# if !(BOOST_WORKAROUND(__MWERKS__, > 0x3100) \ + && BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3201))) +# line BOOST_PP_LINE(__LINE__, call_method.hpp) +# endif + +# define N BOOST_PP_ITERATION() + +template < + class R + BOOST_PP_ENUM_TRAILING_PARAMS_Z(1, N, class A) + > +typename detail::returnable<R>::type +call_method(PyObject* self, char const* name + BOOST_PP_COMMA_IF(N) BOOST_PP_ENUM_BINARY_PARAMS_Z(1, N, A, const& a) + , boost::type<R>* = 0 + ) +{ + PyObject* const result = + PyEval_CallMethod( + self + , const_cast<char*>(name) + , const_cast<char*>("(" BOOST_PP_REPEAT_1ST(N, BOOST_PYTHON_FIXED, "O") ")") + BOOST_PP_REPEAT_1ST(N, BOOST_PYTHON_FAST_ARG_TO_PYTHON_GET, nil) + ); + + // This conversion *must not* be done in the same expression as + // the call, because, in the special case where the result is a + // reference a Python object which was created by converting a C++ + // argument for passing to PyEval_CallFunction, its reference + // count will be 2 until the end of the full expression containing + // the conversion, and that interferes with dangling + // pointer/reference detection. + converter::return_from_python<R> converter; + return converter(result); +} + +# undef N + +#endif // BOOST_PP_ITERATION_DEPTH() +#endif // BOOST_PP_IS_ITERATING diff --git a/boost/python/cast.hpp b/boost/python/cast.hpp new file mode 100644 index 0000000000..31c61dbf82 --- /dev/null +++ b/boost/python/cast.hpp @@ -0,0 +1,106 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef CAST_DWA200269_HPP +# define CAST_DWA200269_HPP + +# include <boost/python/detail/prefix.hpp> + +# include <boost/type_traits/same_traits.hpp> +# include <boost/type_traits/cv_traits.hpp> +# include <boost/type.hpp> +# include <boost/python/base_type_traits.hpp> +# include <boost/python/detail/convertible.hpp> + +namespace boost { namespace python { + +namespace detail +{ + template <class Source, class Target> inline Target* upcast_impl(Source*, Target*); + + template <class Source, class Target> + inline Target* upcast(Source* p, yes_convertible, no_convertible, Target*) + { + return p; + } + + template <class Source, class Target> + inline Target* upcast(Source* p, no_convertible, no_convertible, Target*) + { + typedef typename base_type_traits<Source>::type base; + + return detail::upcast_impl((base*)p, (Target*)0); + } + + template <bool is_same = true> + struct upcaster + { + template <class T> + static inline T* execute(T* x, T*) { return x; } + }; + + template <> + struct upcaster<false> + { + template <class Source, class Target> + static inline Target* execute(Source* x, Target*) + { + return detail::upcast( + x, detail::convertible<Target*>::check(x) + , detail::convertible<Source*>::check((Target*)0) + , (Target*)0); + } + }; + + + template <class Target, class Source> + inline Target* downcast(Source* p, yes_convertible) + { + return static_cast<Target*>(p); + } + + template <class Target, class Source> + inline Target* downcast(Source* p, no_convertible, boost::type<Target>* = 0) + { + typedef typename base_type_traits<Source>::type base; + return (Target*)detail::downcast<base>(p, convertible<Source*>::check((base*)0)); + } + + template <class T> + inline void assert_castable(boost::type<T>* = 0) + { + typedef char must_be_a_complete_type[sizeof(T)]; + } + + template <class Source, class Target> + inline Target* upcast_impl(Source* x, Target*) + { + typedef typename add_cv<Source>::type src_t; + typedef typename add_cv<Target>::type target_t; + bool const same = is_same<src_t,target_t>::value; + + return detail::upcaster<same>::execute(x, (Target*)0); + } +} + +template <class Target, class Source> +inline Target* upcast(Source* x, Target* = 0) +{ + detail::assert_castable<Source>(); + detail::assert_castable<Target>(); + return detail::upcast_impl(x, (Target*)0); + +} + +template <class Target, class Source> +inline Target* downcast(Source* x, Target* = 0) +{ + detail::assert_castable<Source>(); + detail::assert_castable<Target>(); + return detail::downcast<Target>(x, detail::convertible<Source*>::check((Target*)0)); +} + +}} // namespace boost::python + +#endif // CAST_DWA200269_HPP diff --git a/boost/python/class.hpp b/boost/python/class.hpp new file mode 100644 index 0000000000..253667bbd7 --- /dev/null +++ b/boost/python/class.hpp @@ -0,0 +1,655 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef CLASS_DWA200216_HPP +# define CLASS_DWA200216_HPP + +# include <boost/python/detail/prefix.hpp> + +# include <boost/noncopyable.hpp> + +# include <boost/python/class_fwd.hpp> +# include <boost/python/object/class.hpp> + +# include <boost/python/object.hpp> +# include <boost/python/type_id.hpp> +# include <boost/python/data_members.hpp> +# include <boost/python/make_function.hpp> +# include <boost/python/signature.hpp> +# include <boost/python/init.hpp> +# include <boost/python/args_fwd.hpp> + +# include <boost/python/object/class_metadata.hpp> +# include <boost/python/object/pickle_support.hpp> +# include <boost/python/object/add_to_namespace.hpp> + +# include <boost/python/detail/overloads_fwd.hpp> +# include <boost/python/detail/operator_id.hpp> +# include <boost/python/detail/def_helper.hpp> +# include <boost/python/detail/force_instantiate.hpp> +# include <boost/python/detail/unwrap_type_id.hpp> +# include <boost/python/detail/unwrap_wrapper.hpp> + +# include <boost/type_traits/is_same.hpp> +# include <boost/type_traits/is_member_function_pointer.hpp> +# include <boost/type_traits/is_polymorphic.hpp> + +# include <boost/mpl/size.hpp> +# include <boost/mpl/for_each.hpp> +# include <boost/mpl/bool.hpp> +# include <boost/mpl/not.hpp> + +# include <boost/detail/workaround.hpp> + +# if BOOST_WORKAROUND(__MWERKS__, <= 0x3004) \ + /* pro9 reintroduced the bug */ \ + || (BOOST_WORKAROUND(__MWERKS__, > 0x3100) \ + && BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3201))) \ + || BOOST_WORKAROUND(__GNUC__, < 3) + +# define BOOST_PYTHON_NO_MEMBER_POINTER_ORDERING 1 + +# endif + +# ifdef BOOST_PYTHON_NO_MEMBER_POINTER_ORDERING +# include <boost/mpl/and.hpp> +# include <boost/type_traits/is_member_pointer.hpp> +# endif + +namespace boost { namespace python { + +template <class DerivedVisitor> class def_visitor; + +enum no_init_t { no_init }; + +namespace detail +{ + // This function object is used with mpl::for_each to write the id + // of the type a pointer to which is passed as its 2nd compile-time + // argument. into the iterator pointed to by its runtime argument + struct write_type_id + { + write_type_id(type_info**p) : p(p) {} + + // Here's the runtime behavior + template <class T> + void operator()(T*) const + { + *(*p)++ = type_id<T>(); + } + + type_info** p; + }; + + template <class T> + struct is_data_member_pointer + : mpl::and_< + is_member_pointer<T> + , mpl::not_<is_member_function_pointer<T> > + > + {}; + +# ifdef BOOST_PYTHON_NO_MEMBER_POINTER_ORDERING +# define BOOST_PYTHON_DATA_MEMBER_HELPER(D) , detail::is_data_member_pointer<D>() +# define BOOST_PYTHON_YES_DATA_MEMBER , mpl::true_ +# define BOOST_PYTHON_NO_DATA_MEMBER , mpl::false_ +# elif defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) +# define BOOST_PYTHON_DATA_MEMBER_HELPER(D) , 0 +# define BOOST_PYTHON_YES_DATA_MEMBER , int +# define BOOST_PYTHON_NO_DATA_MEMBER , ... +# else +# define BOOST_PYTHON_DATA_MEMBER_HELPER(D) +# define BOOST_PYTHON_YES_DATA_MEMBER +# define BOOST_PYTHON_NO_DATA_MEMBER +# endif + + namespace error + { + // + // A meta-assertion mechanism which prints nice error messages and + // backtraces on lots of compilers. Usage: + // + // assertion<C>::failed + // + // where C is an MPL metafunction class + // + + template <class C> struct assertion_failed { }; + template <class C> struct assertion_ok { typedef C failed; }; + + template <class C> + struct assertion + : mpl::if_<C, assertion_ok<C>, assertion_failed<C> >::type + {}; + + // + // Checks for validity of arguments used to define virtual + // functions with default implementations. + // + + template <class Default> + void not_a_derived_class_member(Default) {} + + template <class T, class Fn> + struct virtual_function_default + { + template <class Default> + static void + must_be_derived_class_member(Default const&) + { + // https://svn.boost.org/trac/boost/ticket/5803 + //typedef typename assertion<mpl::not_<is_same<Default,Fn> > >::failed test0; +# if !BOOST_WORKAROUND(__MWERKS__, <= 0x2407) + typedef typename assertion<is_polymorphic<T> >::failed test1; +# endif + typedef typename assertion<is_member_function_pointer<Fn> >::failed test2; + not_a_derived_class_member<Default>(Fn()); + } + }; + } +} + +// This is the primary mechanism through which users will expose +// C++ classes to Python. +template < + class W // class being wrapped + , class X1 // = detail::not_specified + , class X2 // = detail::not_specified + , class X3 // = detail::not_specified + > +class class_ : public objects::class_base +{ + public: // types + typedef objects::class_base base; + typedef class_<W,X1,X2,X3> self; + typedef typename objects::class_metadata<W,X1,X2,X3> metadata; + typedef W wrapped_type; + + private: // types + + // A helper class which will contain an array of id objects to be + // passed to the base class constructor + struct id_vector + { + typedef typename metadata::bases bases; + + id_vector() + { + // Stick the derived class id into the first element of the array + ids[0] = detail::unwrap_type_id((W*)0, (W*)0); + + // Write the rest of the elements into succeeding positions. + type_info* p = ids + 1; + mpl::for_each(detail::write_type_id(&p), (bases*)0, (add_pointer<mpl::_>*)0); + } + + BOOST_STATIC_CONSTANT( + std::size_t, size = mpl::size<bases>::value + 1); + type_info ids[size]; + }; + friend struct id_vector; + + public: // constructors + + // Construct with the class name, with or without docstring, and default __init__() function + class_(char const* name, char const* doc = 0); + + // Construct with class name, no docstring, and an uncallable __init__ function + class_(char const* name, no_init_t); + + // Construct with class name, docstring, and an uncallable __init__ function + class_(char const* name, char const* doc, no_init_t); + + // Construct with class name and init<> function + template <class DerivedT> + inline class_(char const* name, init_base<DerivedT> const& i) + : base(name, id_vector::size, id_vector().ids) + { + this->initialize(i); + } + + // Construct with class name, docstring and init<> function + template <class DerivedT> + inline class_(char const* name, char const* doc, init_base<DerivedT> const& i) + : base(name, id_vector::size, id_vector().ids, doc) + { + this->initialize(i); + } + + public: // member functions + + // Generic visitation + template <class Derived> + self& def(def_visitor<Derived> const& visitor) + { + visitor.visit(*this); + return *this; + } + + // Wrap a member function or a non-member function which can take + // a T, T cv&, or T cv* as its first parameter, a callable + // python object, or a generic visitor. + template <class F> + self& def(char const* name, F f) + { + this->def_impl( + detail::unwrap_wrapper((W*)0) + , name, f, detail::def_helper<char const*>(0), &f); + return *this; + } + + template <class A1, class A2> + self& def(char const* name, A1 a1, A2 const& a2) + { + this->def_maybe_overloads(name, a1, a2, &a2); + return *this; + } + + template <class Fn, class A1, class A2> + self& def(char const* name, Fn fn, A1 const& a1, A2 const& a2) + { + // The arguments are definitely: + // def(name, function, policy, doc_string) + // def(name, function, doc_string, policy) + + this->def_impl( + detail::unwrap_wrapper((W*)0) + , name, fn + , detail::def_helper<A1,A2>(a1,a2) + , &fn); + + return *this; + } + + template <class Fn, class A1, class A2, class A3> + self& def(char const* name, Fn fn, A1 const& a1, A2 const& a2, A3 const& a3) + { + this->def_impl( + detail::unwrap_wrapper((W*)0) + , name, fn + , detail::def_helper<A1,A2,A3>(a1,a2,a3) + , &fn); + + return *this; + } + + // + // Data member access + // + template <class D> + self& def_readonly(char const* name, D const& d, char const* doc=0) + { + return this->def_readonly_impl(name, d, doc BOOST_PYTHON_DATA_MEMBER_HELPER(D)); + } + + template <class D> + self& def_readwrite(char const* name, D const& d, char const* doc=0) + { + return this->def_readwrite_impl(name, d, doc BOOST_PYTHON_DATA_MEMBER_HELPER(D)); + } + + template <class D> + self& def_readonly(char const* name, D& d, char const* doc=0) + { + return this->def_readonly_impl(name, d, doc BOOST_PYTHON_DATA_MEMBER_HELPER(D)); + } + + template <class D> + self& def_readwrite(char const* name, D& d, char const* doc=0) + { + return this->def_readwrite_impl(name, d, doc BOOST_PYTHON_DATA_MEMBER_HELPER(D)); + } + + // Property creation +# if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) + template <class Get> + self& add_property(char const* name, Get fget, char const* docstr = 0) + { + base::add_property(name, this->make_getter(fget), docstr); + return *this; + } + + template <class Get, class Set> + self& add_property(char const* name, Get fget, Set fset, char const* docstr = 0) + { + base::add_property( + name, this->make_getter(fget), this->make_setter(fset), docstr); + return *this; + } +# else + private: + template <class Get> + self& add_property_impl(char const* name, Get fget, char const* docstr, int) + { + base::add_property(name, this->make_getter(fget), docstr); + return *this; + } + + template <class Get, class Set> + self& add_property_impl(char const* name, Get fget, Set fset, ...) + { + base::add_property( + name, this->make_getter(fget), this->make_setter(fset), 0); + return *this; + } + + public: + template <class Get> + self& add_property(char const* name, Get fget) + { + base::add_property(name, this->make_getter(fget), 0); + return *this; + } + + template <class Get, class DocStrOrSet> + self& add_property(char const* name, Get fget, DocStrOrSet docstr_or_set) + { + this->add_property_impl(name, this->make_getter(fget), docstr_or_set, 0); + return *this; + } + + template <class Get, class Set> + self& + add_property(char const* name, Get fget, Set fset, char const* docstr) + { + base::add_property( + name, this->make_getter(fget), this->make_setter(fset), docstr); + return *this; + } +# endif + + template <class Get> + self& add_static_property(char const* name, Get fget) + { + base::add_static_property(name, object(fget)); + return *this; + } + + template <class Get, class Set> + self& add_static_property(char const* name, Get fget, Set fset) + { + base::add_static_property(name, object(fget), object(fset)); + return *this; + } + + template <class U> + self& setattr(char const* name, U const& x) + { + this->base::setattr(name, object(x)); + return *this; + } + + // Pickle support + template <typename PickleSuiteType> + self& def_pickle(PickleSuiteType const& x) + { + error_messages::must_be_derived_from_pickle_suite(x); + detail::pickle_suite_finalize<PickleSuiteType>::register_( + *this, + &PickleSuiteType::getinitargs, + &PickleSuiteType::getstate, + &PickleSuiteType::setstate, + PickleSuiteType::getstate_manages_dict()); + return *this; + } + + self& enable_pickling() + { + this->base::enable_pickling_(false); + return *this; + } + + self& staticmethod(char const* name) + { + this->make_method_static(name); + return *this; + } + private: // helper functions + + // Builds a method for this class around the given [member] + // function pointer or object, appropriately adjusting the type of + // the first signature argument so that if f is a member of a + // (possibly not wrapped) base class of T, an lvalue argument of + // type T will be required. + // + // @group PropertyHelpers { + template <class F> + object make_getter(F f) + { + typedef typename api::is_object_operators<F>::type is_obj_or_proxy; + + return this->make_fn_impl( + detail::unwrap_wrapper((W*)0) + , f, is_obj_or_proxy(), (char*)0, detail::is_data_member_pointer<F>() + ); + } + + template <class F> + object make_setter(F f) + { + typedef typename api::is_object_operators<F>::type is_obj_or_proxy; + + return this->make_fn_impl( + detail::unwrap_wrapper((W*)0) + , f, is_obj_or_proxy(), (int*)0, detail::is_data_member_pointer<F>() + ); + } + + template <class T, class F> + object make_fn_impl(T*, F const& f, mpl::false_, void*, mpl::false_) + { + return python::make_function(f, default_call_policies(), detail::get_signature(f, (T*)0)); + } + + template <class T, class D, class B> + object make_fn_impl(T*, D B::*pm_, mpl::false_, char*, mpl::true_) + { + D T::*pm = pm_; + return python::make_getter(pm); + } + + template <class T, class D, class B> + object make_fn_impl(T*, D B::*pm_, mpl::false_, int*, mpl::true_) + { + D T::*pm = pm_; + return python::make_setter(pm); + } + + template <class T, class F> + object make_fn_impl(T*, F const& x, mpl::true_, void*, mpl::false_) + { + return x; + } + // } + + template <class D, class B> + self& def_readonly_impl( + char const* name, D B::*pm_, char const* doc BOOST_PYTHON_YES_DATA_MEMBER) + { + return this->add_property(name, pm_, doc); + } + + template <class D, class B> + self& def_readwrite_impl( + char const* name, D B::*pm_, char const* doc BOOST_PYTHON_YES_DATA_MEMBER) + { + return this->add_property(name, pm_, pm_, doc); + } + + template <class D> + self& def_readonly_impl( + char const* name, D& d, char const* BOOST_PYTHON_NO_DATA_MEMBER) + { + return this->add_static_property(name, python::make_getter(d)); + } + + template <class D> + self& def_readwrite_impl( + char const* name, D& d, char const* BOOST_PYTHON_NO_DATA_MEMBER) + { + return this->add_static_property(name, python::make_getter(d), python::make_setter(d)); + } + + template <class DefVisitor> + inline void initialize(DefVisitor const& i) + { + metadata::register_(); // set up runtime metadata/conversions + + typedef typename metadata::holder holder; + this->set_instance_size( objects::additional_instance_size<holder>::value ); + + this->def(i); + } + + inline void initialize(no_init_t) + { + metadata::register_(); // set up runtime metadata/conversions + this->def_no_init(); + } + + // + // These two overloads discriminate between def() as applied to a + // generic visitor and everything else. + // + // @group def_impl { + template <class T, class Helper, class LeafVisitor, class Visitor> + inline void def_impl( + T* + , char const* name + , LeafVisitor + , Helper const& helper + , def_visitor<Visitor> const* v + ) + { + v->visit(*this, name, helper); + } + + template <class T, class Fn, class Helper> + inline void def_impl( + T* + , char const* name + , Fn fn + , Helper const& helper + , ... + ) + { + objects::add_to_namespace( + *this + , name + , make_function( + fn + , helper.policies() + , helper.keywords() + , detail::get_signature(fn, (T*)0) + ) + , helper.doc() + ); + + this->def_default(name, fn, helper, mpl::bool_<Helper::has_default_implementation>()); + } + // } + + // + // These two overloads handle the definition of default + // implementation overloads for virtual functions. The second one + // handles the case where no default implementation was specified. + // + // @group def_default { + template <class Fn, class Helper> + inline void def_default( + char const* name + , Fn + , Helper const& helper + , mpl::bool_<true>) + { + detail::error::virtual_function_default<W,Fn>::must_be_derived_class_member( + helper.default_implementation()); + + objects::add_to_namespace( + *this, name, + make_function( + helper.default_implementation(), helper.policies(), helper.keywords()) + ); + } + + template <class Fn, class Helper> + inline void def_default(char const*, Fn, Helper const&, mpl::bool_<false>) + { } + // } + + // + // These two overloads discriminate between def() as applied to + // regular functions and def() as applied to the result of + // BOOST_PYTHON_FUNCTION_OVERLOADS(). The final argument is used to + // discriminate. + // + // @group def_maybe_overloads { + template <class OverloadsT, class SigT> + void def_maybe_overloads( + char const* name + , SigT sig + , OverloadsT const& overloads + , detail::overloads_base const*) + + { + // convert sig to a type_list (see detail::get_signature in signature.hpp) + // before calling detail::define_with_defaults. + detail::define_with_defaults( + name, overloads, *this, detail::get_signature(sig)); + } + + template <class Fn, class A1> + void def_maybe_overloads( + char const* name + , Fn fn + , A1 const& a1 + , ...) + { + this->def_impl( + detail::unwrap_wrapper((W*)0) + , name + , fn + , detail::def_helper<A1>(a1) + , &fn + ); + + } + // } +}; + + +// +// implementations +// + +template <class W, class X1, class X2, class X3> +inline class_<W,X1,X2,X3>::class_(char const* name, char const* doc) + : base(name, id_vector::size, id_vector().ids, doc) +{ + this->initialize(init<>()); +// select_holder::assert_default_constructible(); +} + +template <class W, class X1, class X2, class X3> +inline class_<W,X1,X2,X3>::class_(char const* name, no_init_t) + : base(name, id_vector::size, id_vector().ids) +{ + this->initialize(no_init); +} + +template <class W, class X1, class X2, class X3> +inline class_<W,X1,X2,X3>::class_(char const* name, char const* doc, no_init_t) + : base(name, id_vector::size, id_vector().ids, doc) +{ + this->initialize(no_init); +} + +}} // namespace boost::python + +# undef BOOST_PYTHON_DATA_MEMBER_HELPER +# undef BOOST_PYTHON_YES_DATA_MEMBER +# undef BOOST_PYTHON_NO_DATA_MEMBER +# undef BOOST_PYTHON_NO_MEMBER_POINTER_ORDERING + +#endif // CLASS_DWA200216_HPP diff --git a/boost/python/class_fwd.hpp b/boost/python/class_fwd.hpp new file mode 100644 index 0000000000..528e18a1dc --- /dev/null +++ b/boost/python/class_fwd.hpp @@ -0,0 +1,24 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef CLASS_FWD_DWA200222_HPP +# define CLASS_FWD_DWA200222_HPP + +# include <boost/python/detail/prefix.hpp> +# include <boost/python/detail/not_specified.hpp> + +namespace boost { namespace python { + +template < + class T // class being wrapped + // arbitrarily-ordered optional arguments. Full qualification needed for MSVC6 + , class X1 = ::boost::python::detail::not_specified + , class X2 = ::boost::python::detail::not_specified + , class X3 = ::boost::python::detail::not_specified + > +class class_; + +}} // namespace boost::python + +#endif // CLASS_FWD_DWA200222_HPP diff --git a/boost/python/converter/arg_from_python.hpp b/boost/python/converter/arg_from_python.hpp new file mode 100644 index 0000000000..e2edce7e1c --- /dev/null +++ b/boost/python/converter/arg_from_python.hpp @@ -0,0 +1,336 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef ARG_FROM_PYTHON_DWA2002127_HPP +# define ARG_FROM_PYTHON_DWA2002127_HPP + +# include <boost/python/detail/prefix.hpp> +# include <boost/python/converter/from_python.hpp> +# include <boost/python/detail/indirect_traits.hpp> +# include <boost/type_traits/transform_traits.hpp> +# include <boost/type_traits/cv_traits.hpp> +# include <boost/python/converter/rvalue_from_python_data.hpp> +# include <boost/mpl/eval_if.hpp> +# include <boost/mpl/if.hpp> +# include <boost/mpl/identity.hpp> +# include <boost/mpl/and.hpp> +# include <boost/mpl/or.hpp> +# include <boost/mpl/not.hpp> +# include <boost/python/converter/registry.hpp> +# include <boost/python/converter/registered.hpp> +# include <boost/python/converter/registered_pointee.hpp> +# include <boost/python/detail/void_ptr.hpp> +# include <boost/python/back_reference.hpp> +# include <boost/python/detail/referent_storage.hpp> +# include <boost/python/converter/obj_mgr_arg_from_python.hpp> + +namespace boost { namespace python +{ + template <class T> struct arg_from_python; +}} + +// This header defines Python->C++ function argument converters, +// parametrized on the argument type. + +namespace boost { namespace python { namespace converter { + +// +// lvalue converters +// +// These require that an lvalue of the type U is stored somewhere in +// the Python object being converted. + +// Used when T == U*const& +template <class T> +struct pointer_cref_arg_from_python +{ + typedef T result_type; + + pointer_cref_arg_from_python(PyObject*); + T operator()() const; + bool convertible() const; + + private: // storage for a U* + // needed because not all compilers will let us declare U* as the + // return type of operator() -- we return U*const& instead + typename python::detail::referent_storage<T>::type m_result; +}; + +// Base class for pointer and reference converters +struct arg_lvalue_from_python_base +{ + public: // member functions + arg_lvalue_from_python_base(void* result); + bool convertible() const; + + protected: // member functions + void*const& result() const; + + private: // data members + void* m_result; +}; + +// Used when T == U* +template <class T> +struct pointer_arg_from_python : arg_lvalue_from_python_base +{ + typedef T result_type; + + pointer_arg_from_python(PyObject*); + T operator()() const; +}; + +// Used when T == U& and (T != V const& or T == W volatile&) +template <class T> +struct reference_arg_from_python : arg_lvalue_from_python_base +{ + typedef T result_type; + + reference_arg_from_python(PyObject*); + T operator()() const; +}; + +// =================== + +// +// rvalue converters +// +// These require only that an object of type T can be created from +// the given Python object, but not that the T object exist +// somewhere in storage. +// + +// Used when T is a plain value (non-pointer, non-reference) type or +// a (non-volatile) const reference to a plain value type. +template <class T> +struct arg_rvalue_from_python +{ + typedef typename boost::add_reference< + T + // We can't add_const here, or it would be impossible to pass + // auto_ptr<U> args from Python to C++ + >::type result_type; + + arg_rvalue_from_python(PyObject*); + bool convertible() const; + +# if BOOST_MSVC < 1301 || _MSC_FULL_VER > 13102196 + typename arg_rvalue_from_python<T>:: +# endif + result_type operator()(); + + private: + rvalue_from_python_data<result_type> m_data; + PyObject* m_source; +}; + + +// ================== + +// Converts to a (PyObject*,T) bundle, for when you need a reference +// back to the Python object +template <class T> +struct back_reference_arg_from_python + : boost::python::arg_from_python<typename T::type> +{ + typedef T result_type; + + back_reference_arg_from_python(PyObject*); + T operator()(); + private: + typedef boost::python::arg_from_python<typename T::type> base; + PyObject* m_source; +}; + + +// ================== + +template <class C, class T, class F> +struct if_2 +{ + typedef typename mpl::eval_if<C, mpl::identity<T>, F>::type type; +}; + +// This metafunction selects the appropriate arg_from_python converter +// type for an argument of type T. +template <class T> +struct select_arg_from_python +{ + typedef typename if_2< + is_object_manager<T> + , object_manager_value_arg_from_python<T> + , if_2< + is_reference_to_object_manager<T> + , object_manager_ref_arg_from_python<T> + , if_2< + is_pointer<T> + , pointer_arg_from_python<T> + , if_2< + mpl::and_< + indirect_traits::is_reference_to_pointer<T> + , indirect_traits::is_reference_to_const<T> + , mpl::not_<indirect_traits::is_reference_to_volatile<T> > + > + , pointer_cref_arg_from_python<T> + , if_2< + mpl::or_< + indirect_traits::is_reference_to_non_const<T> + , indirect_traits::is_reference_to_volatile<T> + > + , reference_arg_from_python<T> + , mpl::if_< + boost::python::is_back_reference<T> + , back_reference_arg_from_python<T> + , arg_rvalue_from_python<T> + > + > + > + > + > + >::type type; +}; + +// ================== + +// +// implementations +// + +// arg_lvalue_from_python_base +// +inline arg_lvalue_from_python_base::arg_lvalue_from_python_base(void* result) + : m_result(result) +{ +} + +inline bool arg_lvalue_from_python_base::convertible() const +{ + return m_result != 0; +} + +inline void*const& arg_lvalue_from_python_base::result() const +{ + return m_result; +} + +// pointer_cref_arg_from_python +// +namespace detail +{ + // null_ptr_reference -- a function returning a reference to a null + // pointer of type U. Needed so that extractors for T*const& can + // convert Python's None. + template <class T> + struct null_ptr_owner + { + static T value; + }; + template <class T> T null_ptr_owner<T>::value = 0; + + template <class U> + inline U& null_ptr_reference(U&(*)()) + { + return null_ptr_owner<U>::value; + } +} + +template <class T> +inline pointer_cref_arg_from_python<T>::pointer_cref_arg_from_python(PyObject* p) +{ + // T == U*const&: store a U* in the m_result storage. Nonzero + // indicates success. If find returns nonzero, it's a pointer to + // a U object. + python::detail::write_void_ptr_reference( + m_result.bytes + , p == Py_None ? p : converter::get_lvalue_from_python(p, registered_pointee<T>::converters) + , (T(*)())0); +} + +template <class T> +inline bool pointer_cref_arg_from_python<T>::convertible() const +{ + return python::detail::void_ptr_to_reference(m_result.bytes, (T(*)())0) != 0; +} +template <class T> +inline T pointer_cref_arg_from_python<T>::operator()() const +{ + return (*(void**)m_result.bytes == Py_None) // None ==> 0 + ? detail::null_ptr_reference((T(*)())0) + // Otherwise, return a U*const& to the m_result storage. + : python::detail::void_ptr_to_reference(m_result.bytes, (T(*)())0); +} + +// pointer_arg_from_python +// +template <class T> +inline pointer_arg_from_python<T>::pointer_arg_from_python(PyObject* p) + : arg_lvalue_from_python_base( + p == Py_None ? p : converter::get_lvalue_from_python(p, registered_pointee<T>::converters)) +{ +} + +template <class T> +inline T pointer_arg_from_python<T>::operator()() const +{ + return (result() == Py_None) ? 0 : T(result()); +} + +// reference_arg_from_python +// +template <class T> +inline reference_arg_from_python<T>::reference_arg_from_python(PyObject* p) + : arg_lvalue_from_python_base(converter::get_lvalue_from_python(p,registered<T>::converters)) +{ +} + +template <class T> +inline T reference_arg_from_python<T>::operator()() const +{ + return python::detail::void_ptr_to_reference(result(), (T(*)())0); +} + + +// arg_rvalue_from_python +// +template <class T> +inline arg_rvalue_from_python<T>::arg_rvalue_from_python(PyObject* obj) + : m_data(converter::rvalue_from_python_stage1(obj, registered<T>::converters)) + , m_source(obj) +{ +} + +template <class T> +inline bool arg_rvalue_from_python<T>::convertible() const +{ + return m_data.stage1.convertible != 0; +} + +template <class T> +inline typename arg_rvalue_from_python<T>::result_type +arg_rvalue_from_python<T>::operator()() +{ + if (m_data.stage1.construct != 0) + m_data.stage1.construct(m_source, &m_data.stage1); + + return python::detail::void_ptr_to_reference(m_data.stage1.convertible, (result_type(*)())0); +} + +// back_reference_arg_from_python +// +template <class T> +back_reference_arg_from_python<T>::back_reference_arg_from_python(PyObject* x) + : base(x), m_source(x) +{ +} + +template <class T> +inline T +back_reference_arg_from_python<T>::operator()() +{ + return T(m_source, base::operator()()); +} + +}}} // namespace boost::python::converter + +#endif // ARG_FROM_PYTHON_DWA2002127_HPP diff --git a/boost/python/converter/arg_to_python.hpp b/boost/python/converter/arg_to_python.hpp new file mode 100644 index 0000000000..3a19ec4395 --- /dev/null +++ b/boost/python/converter/arg_to_python.hpp @@ -0,0 +1,261 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef ARG_TO_PYTHON_DWA200265_HPP +# define ARG_TO_PYTHON_DWA200265_HPP + +# include <boost/python/ptr.hpp> +# include <boost/python/tag.hpp> +# include <boost/python/to_python_indirect.hpp> + +# include <boost/python/converter/registered.hpp> +# include <boost/python/converter/registered_pointee.hpp> +# include <boost/python/converter/arg_to_python_base.hpp> +# include <boost/python/converter/shared_ptr_to_python.hpp> +// Bring in specializations +# include <boost/python/converter/builtin_converters.hpp> + +# include <boost/python/object/function_handle.hpp> + +# include <boost/python/base_type_traits.hpp> + +# include <boost/python/detail/indirect_traits.hpp> +# include <boost/python/detail/convertible.hpp> +# include <boost/python/detail/string_literal.hpp> +# include <boost/python/detail/value_is_shared_ptr.hpp> + +# include <boost/type_traits/cv_traits.hpp> +# include <boost/type_traits/composite_traits.hpp> +# include <boost/type_traits/function_traits.hpp> + + +# include <boost/mpl/or.hpp> + +namespace boost { namespace python { namespace converter { + +template <class T> struct is_object_manager; + +namespace detail +{ + template <class T> + struct function_arg_to_python : handle<> + { + function_arg_to_python(T const& x); + }; + + template <class T> + struct reference_arg_to_python : handle<> + { + reference_arg_to_python(T& x); + private: + static PyObject* get_object(T& x); + }; + + template <class T> + struct shared_ptr_arg_to_python : handle<> + { + shared_ptr_arg_to_python(T const& x); + private: + static PyObject* get_object(T& x); + }; + + template <class T> + struct value_arg_to_python : arg_to_python_base + { + // Throw an exception if the conversion can't succeed + value_arg_to_python(T const&); + }; + + template <class Ptr> + struct pointer_deep_arg_to_python : arg_to_python_base + { + // Throw an exception if the conversion can't succeed + pointer_deep_arg_to_python(Ptr); + }; + + template <class Ptr> + struct pointer_shallow_arg_to_python : handle<> + { + // Throw an exception if the conversion can't succeed + pointer_shallow_arg_to_python(Ptr); + private: + static PyObject* get_object(Ptr p); + }; + + // Convert types that manage a Python object to_python + template <class T> + struct object_manager_arg_to_python + { + object_manager_arg_to_python(T const& x) : m_src(x) {} + + PyObject* get() const + { + return python::upcast<PyObject>(get_managed_object(m_src, tag)); + } + + private: + T const& m_src; + }; + + template <class T> + struct select_arg_to_python + { + typedef typename unwrap_reference<T>::type unwrapped_referent; + typedef typename unwrap_pointer<T>::type unwrapped_ptr; + + typedef typename mpl::if_< + // Special handling for char const[N]; interpret them as char + // const* for the sake of conversion + python::detail::is_string_literal<T const> + , arg_to_python<char const*> + + , typename mpl::if_< + python::detail::value_is_shared_ptr<T> + , shared_ptr_arg_to_python<T> + + , typename mpl::if_< + mpl::or_< + is_function<T> + , indirect_traits::is_pointer_to_function<T> + , is_member_function_pointer<T> + > + , function_arg_to_python<T> + + , typename mpl::if_< + is_object_manager<T> + , object_manager_arg_to_python<T> + + , typename mpl::if_< + is_pointer<T> + , pointer_deep_arg_to_python<T> + + , typename mpl::if_< + is_pointer_wrapper<T> + , pointer_shallow_arg_to_python<unwrapped_ptr> + + , typename mpl::if_< + is_reference_wrapper<T> + , reference_arg_to_python<unwrapped_referent> + , value_arg_to_python<T> + >::type + >::type + >::type + >::type + >::type + >::type + >::type + + type; + }; +} + +template <class T> +struct arg_to_python + : detail::select_arg_to_python<T>::type +{ + typedef typename detail::select_arg_to_python<T>::type base; + public: // member functions + // Throw an exception if the conversion can't succeed + arg_to_python(T const& x); +}; + +// +// implementations +// +namespace detail +{ + // reject_raw_object_ptr -- cause a compile-time error if the user + // should pass a raw Python object pointer + using python::detail::yes_convertible; + using python::detail::no_convertible; + using python::detail::unspecialized; + + template <class T> struct cannot_convert_raw_PyObject; + + template <class T, class Convertibility> + struct reject_raw_object_helper + { + static void error(Convertibility) + { + cannot_convert_raw_PyObject<T*>::to_python_use_handle_instead(); + } + static void error(...) {} + }; + + template <class T> + inline void reject_raw_object_ptr(T*) + { + reject_raw_object_helper<T,yes_convertible>::error( + python::detail::convertible<PyObject const volatile*>::check((T*)0)); + + typedef typename remove_cv<T>::type value_type; + + reject_raw_object_helper<T,no_convertible>::error( + python::detail::convertible<unspecialized*>::check( + (base_type_traits<value_type>*)0 + )); + } + // --------- + + template <class T> + inline function_arg_to_python<T>::function_arg_to_python(T const& x) + : handle<>(python::objects::make_function_handle(x)) + { + } + + template <class T> + inline value_arg_to_python<T>::value_arg_to_python(T const& x) + : arg_to_python_base(&x, registered<T>::converters) + { + } + + template <class Ptr> + inline pointer_deep_arg_to_python<Ptr>::pointer_deep_arg_to_python(Ptr x) + : arg_to_python_base(x, registered_pointee<Ptr>::converters) + { + detail::reject_raw_object_ptr((Ptr)0); + } + + template <class T> + inline PyObject* reference_arg_to_python<T>::get_object(T& x) + { + to_python_indirect<T&,python::detail::make_reference_holder> convert; + return convert(x); + } + + template <class T> + inline reference_arg_to_python<T>::reference_arg_to_python(T& x) + : handle<>(reference_arg_to_python<T>::get_object(x)) + { + } + + template <class T> + inline shared_ptr_arg_to_python<T>::shared_ptr_arg_to_python(T const& x) + : handle<>(shared_ptr_to_python(x)) + { + } + + template <class Ptr> + inline pointer_shallow_arg_to_python<Ptr>::pointer_shallow_arg_to_python(Ptr x) + : handle<>(pointer_shallow_arg_to_python<Ptr>::get_object(x)) + { + detail::reject_raw_object_ptr((Ptr)0); + } + + template <class Ptr> + inline PyObject* pointer_shallow_arg_to_python<Ptr>::get_object(Ptr x) + { + to_python_indirect<Ptr,python::detail::make_reference_holder> convert; + return convert(x); + } +} + +template <class T> +inline arg_to_python<T>::arg_to_python(T const& x) + : base(x) +{} + +}}} // namespace boost::python::converter + +#endif // ARG_TO_PYTHON_DWA200265_HPP diff --git a/boost/python/converter/arg_to_python_base.hpp b/boost/python/converter/arg_to_python_base.hpp new file mode 100644 index 0000000000..d85b302e48 --- /dev/null +++ b/boost/python/converter/arg_to_python_base.hpp @@ -0,0 +1,32 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef ARG_TO_PYTHON_BASE_DWA200237_HPP +# define ARG_TO_PYTHON_BASE_DWA200237_HPP +# include <boost/python/handle.hpp> + +namespace boost { namespace python { namespace converter { + +struct registration; + +namespace detail +{ + struct BOOST_PYTHON_DECL arg_to_python_base +# if !defined(BOOST_MSVC) || BOOST_MSVC <= 1300 || _MSC_FULL_VER > 13102179 + : handle<> +# endif + { + arg_to_python_base(void const volatile* source, registration const&); +# if defined(BOOST_MSVC) && BOOST_MSVC > 1300 && _MSC_FULL_VER <= 13102179 + PyObject* get() const { return m_ptr.get(); } + PyObject* release() { return m_ptr.release(); } + private: + handle<> m_ptr; +# endif + }; +} + +}}} // namespace boost::python::converter + +#endif // ARG_TO_PYTHON_BASE_DWA200237_HPP diff --git a/boost/python/converter/as_to_python_function.hpp b/boost/python/converter/as_to_python_function.hpp new file mode 100644 index 0000000000..19a3efaafc --- /dev/null +++ b/boost/python/converter/as_to_python_function.hpp @@ -0,0 +1,49 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef AS_TO_PYTHON_FUNCTION_DWA2002121_HPP +# define AS_TO_PYTHON_FUNCTION_DWA2002121_HPP +# include <boost/python/converter/to_python_function_type.hpp> + +namespace boost { namespace python { namespace converter { + +// Given a typesafe to_python conversion function, produces a +// to_python_function_t which can be registered in the usual way. +template <class T, class ToPython> +struct as_to_python_function +{ + // Assertion functions used to prevent wrapping of converters + // which take non-const reference parameters. The T* argument in + // the first overload ensures it isn't used in case T is a + // reference. + template <class U> + static void convert_function_must_take_value_or_const_reference(U(*)(T), int, T* = 0) {} + template <class U> + static void convert_function_must_take_value_or_const_reference(U(*)(T const&), long ...) {} + + static PyObject* convert(void const* x) + { + convert_function_must_take_value_or_const_reference(&ToPython::convert, 1L); + + // Yes, the const_cast below opens a hole in const-correctness, + // but it's needed to convert auto_ptr<U> to python. + // + // How big a hole is it? It allows ToPython::convert() to be + // a function which modifies its argument. The upshot is that + // client converters applied to const objects may invoke + // undefined behavior. The damage, however, is limited by the + // use of the assertion function. Thus, the only way this can + // modify its argument is if T is an auto_ptr-like type. There + // is still a const-correctness hole w.r.t. auto_ptr<U> const, + // but c'est la vie. + return ToPython::convert(*const_cast<T*>(static_cast<T const*>(x))); + } +#ifndef BOOST_PYTHON_NO_PY_SIGNATURES + static PyTypeObject const * get_pytype() { return ToPython::get_pytype(); } +#endif +}; + +}}} // namespace boost::python::converter + +#endif // AS_TO_PYTHON_FUNCTION_DWA2002121_HPP diff --git a/boost/python/converter/builtin_converters.hpp b/boost/python/converter/builtin_converters.hpp new file mode 100644 index 0000000000..c2e01c03d3 --- /dev/null +++ b/boost/python/converter/builtin_converters.hpp @@ -0,0 +1,190 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef BUILTIN_CONVERTERS_DWA2002124_HPP +# define BUILTIN_CONVERTERS_DWA2002124_HPP +# include <boost/python/detail/prefix.hpp> +# include <boost/python/detail/none.hpp> +# include <boost/python/handle.hpp> +# include <boost/python/ssize_t.hpp> +# include <boost/implicit_cast.hpp> +# include <string> +# include <complex> +# include <boost/limits.hpp> + +// Since all we can use to decide how to convert an object to_python +// is its C++ type, there can be only one such converter for each +// type. Therefore, for built-in conversions we can bypass registry +// lookups using explicit specializations of arg_to_python and +// result_to_python. + +namespace boost { namespace python { + +namespace converter +{ + template <class T> struct arg_to_python; + BOOST_PYTHON_DECL PyObject* do_return_to_python(char); + BOOST_PYTHON_DECL PyObject* do_return_to_python(char const*); + BOOST_PYTHON_DECL PyObject* do_return_to_python(PyObject*); + BOOST_PYTHON_DECL PyObject* do_arg_to_python(PyObject*); +} + +// Provide specializations of to_python_value +template <class T> struct to_python_value; + +namespace detail +{ + // Since there's no registry lookup, always report the existence of + // a converter. + struct builtin_to_python + { + // This information helps make_getter() decide whether to try to + // return an internal reference or not. I don't like it much, + // but it will have to serve for now. + BOOST_STATIC_CONSTANT(bool, uses_registry = false); + }; +} + +// Use expr to create the PyObject corresponding to x +# define BOOST_PYTHON_RETURN_TO_PYTHON_BY_VALUE(T, expr, pytype)\ + template <> struct to_python_value<T&> \ + : detail::builtin_to_python \ + { \ + inline PyObject* operator()(T const& x) const \ + { \ + return (expr); \ + } \ + inline PyTypeObject const* get_pytype() const \ + { \ + return (pytype); \ + } \ + }; \ + template <> struct to_python_value<T const&> \ + : detail::builtin_to_python \ + { \ + inline PyObject* operator()(T const& x) const \ + { \ + return (expr); \ + } \ + inline PyTypeObject const* get_pytype() const \ + { \ + return (pytype); \ + } \ + }; + +# define BOOST_PYTHON_ARG_TO_PYTHON_BY_VALUE(T, expr) \ + namespace converter \ + { \ + template <> struct arg_to_python< T > \ + : handle<> \ + { \ + arg_to_python(T const& x) \ + : python::handle<>(expr) {} \ + }; \ + } + +// Specialize argument and return value converters for T using expr +# define BOOST_PYTHON_TO_PYTHON_BY_VALUE(T, expr, pytype) \ + BOOST_PYTHON_RETURN_TO_PYTHON_BY_VALUE(T,expr, pytype) \ + BOOST_PYTHON_ARG_TO_PYTHON_BY_VALUE(T,expr) + +// Specialize converters for signed and unsigned T to Python Int +#if PY_VERSION_HEX >= 0x03000000 + +# define BOOST_PYTHON_TO_INT(T) \ + BOOST_PYTHON_TO_PYTHON_BY_VALUE(signed T, ::PyLong_FromLong(x), &PyLong_Type) \ + BOOST_PYTHON_TO_PYTHON_BY_VALUE(unsigned T, ::PyLong_FromUnsignedLong(x), &PyLong_Type) + +#else + +# define BOOST_PYTHON_TO_INT(T) \ + BOOST_PYTHON_TO_PYTHON_BY_VALUE(signed T, ::PyInt_FromLong(x), &PyInt_Type) \ + BOOST_PYTHON_TO_PYTHON_BY_VALUE( \ + unsigned T \ + , static_cast<unsigned long>(x) > static_cast<unsigned long>( \ + (std::numeric_limits<long>::max)()) \ + ? ::PyLong_FromUnsignedLong(x) \ + : ::PyInt_FromLong(x), &PyInt_Type) +#endif + +// Bool is not signed. +#if PY_VERSION_HEX >= 0x02030000 +BOOST_PYTHON_TO_PYTHON_BY_VALUE(bool, ::PyBool_FromLong(x), &PyBool_Type) +#else +BOOST_PYTHON_TO_PYTHON_BY_VALUE(bool, ::PyInt_FromLong(x), &PyInt_Type) +#endif + +// note: handles signed char and unsigned char, but not char (see below) +BOOST_PYTHON_TO_INT(char) + +BOOST_PYTHON_TO_INT(short) +BOOST_PYTHON_TO_INT(int) +BOOST_PYTHON_TO_INT(long) + +# if defined(_MSC_VER) && defined(_WIN64) && PY_VERSION_HEX < 0x03000000 +/* Under 64-bit Windows std::size_t is "unsigned long long". To avoid + getting a Python long for each std::size_t the value is checked before + the conversion. A std::size_t is converted to a simple Python int + if possible; a Python long appears only if the value is too small or + too large to fit into a simple int. */ +BOOST_PYTHON_TO_PYTHON_BY_VALUE( + signed BOOST_PYTHON_LONG_LONG, + ( x < static_cast<signed BOOST_PYTHON_LONG_LONG>( + (std::numeric_limits<long>::min)()) + || x > static_cast<signed BOOST_PYTHON_LONG_LONG>( + (std::numeric_limits<long>::max)())) + ? ::PyLong_FromLongLong(x) + : ::PyInt_FromLong(static_cast<long>(x)), &PyInt_Type) +BOOST_PYTHON_TO_PYTHON_BY_VALUE( + unsigned BOOST_PYTHON_LONG_LONG, + x > static_cast<unsigned BOOST_PYTHON_LONG_LONG>( + (std::numeric_limits<long>::max)()) + ? ::PyLong_FromUnsignedLongLong(x) + : ::PyInt_FromLong(static_cast<long>(x)), &PyInt_Type) +// +# elif defined(HAVE_LONG_LONG) // using Python's macro instead of Boost's + // - we don't seem to get the config right + // all the time. +BOOST_PYTHON_TO_PYTHON_BY_VALUE(signed BOOST_PYTHON_LONG_LONG, ::PyLong_FromLongLong(x), &PyLong_Type) +BOOST_PYTHON_TO_PYTHON_BY_VALUE(unsigned BOOST_PYTHON_LONG_LONG, ::PyLong_FromUnsignedLongLong(x), &PyLong_Type) +# endif + +# undef BOOST_TO_PYTHON_INT + +#if PY_VERSION_HEX >= 0x03000000 +BOOST_PYTHON_TO_PYTHON_BY_VALUE(char, converter::do_return_to_python(x), &PyUnicode_Type) +BOOST_PYTHON_TO_PYTHON_BY_VALUE(char const*, converter::do_return_to_python(x), &PyUnicode_Type) +BOOST_PYTHON_TO_PYTHON_BY_VALUE(std::string, ::PyUnicode_FromStringAndSize(x.data(),implicit_cast<ssize_t>(x.size())), &PyUnicode_Type) +#else +BOOST_PYTHON_TO_PYTHON_BY_VALUE(char, converter::do_return_to_python(x), &PyString_Type) +BOOST_PYTHON_TO_PYTHON_BY_VALUE(char const*, converter::do_return_to_python(x), &PyString_Type) +BOOST_PYTHON_TO_PYTHON_BY_VALUE(std::string, ::PyString_FromStringAndSize(x.data(),implicit_cast<ssize_t>(x.size())), &PyString_Type) +#endif + +#if defined(Py_USING_UNICODE) && !defined(BOOST_NO_STD_WSTRING) +BOOST_PYTHON_TO_PYTHON_BY_VALUE(std::wstring, ::PyUnicode_FromWideChar(x.data(),implicit_cast<ssize_t>(x.size())), &PyUnicode_Type) +# endif +BOOST_PYTHON_TO_PYTHON_BY_VALUE(float, ::PyFloat_FromDouble(x), &PyFloat_Type) +BOOST_PYTHON_TO_PYTHON_BY_VALUE(double, ::PyFloat_FromDouble(x), &PyFloat_Type) +BOOST_PYTHON_TO_PYTHON_BY_VALUE(long double, ::PyFloat_FromDouble(x), &PyFloat_Type) +BOOST_PYTHON_RETURN_TO_PYTHON_BY_VALUE(PyObject*, converter::do_return_to_python(x), 0) +BOOST_PYTHON_TO_PYTHON_BY_VALUE(std::complex<float>, ::PyComplex_FromDoubles(x.real(), x.imag()), &PyComplex_Type) +BOOST_PYTHON_TO_PYTHON_BY_VALUE(std::complex<double>, ::PyComplex_FromDoubles(x.real(), x.imag()), &PyComplex_Type) +BOOST_PYTHON_TO_PYTHON_BY_VALUE(std::complex<long double>, ::PyComplex_FromDoubles(x.real(), x.imag()), &PyComplex_Type) + +# undef BOOST_PYTHON_RETURN_TO_PYTHON_BY_VALUE +# undef BOOST_PYTHON_ARG_TO_PYTHON_BY_VALUE +# undef BOOST_PYTHON_TO_PYTHON_BY_VALUE +# undef BOOST_PYTHON_TO_INT + +namespace converter +{ + + void initialize_builtin_converters(); + +} + +}} // namespace boost::python::converter + +#endif // BUILTIN_CONVERTERS_DWA2002124_HPP diff --git a/boost/python/converter/constructor_function.hpp b/boost/python/converter/constructor_function.hpp new file mode 100644 index 0000000000..814aa7d763 --- /dev/null +++ b/boost/python/converter/constructor_function.hpp @@ -0,0 +1,17 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef CONSTRUCTOR_FUNCTION_DWA200278_HPP +# define CONSTRUCTOR_FUNCTION_DWA200278_HPP + +namespace boost { namespace python { namespace converter { + +// Declares the type of functions used to construct C++ objects for +// rvalue from_python conversions. +struct rvalue_from_python_stage1_data; +typedef void (*constructor_function)(PyObject* source, rvalue_from_python_stage1_data*); + +}}} // namespace boost::python::converter + +#endif // CONSTRUCTOR_FUNCTION_DWA200278_HPP diff --git a/boost/python/converter/context_result_converter.hpp b/boost/python/converter/context_result_converter.hpp new file mode 100644 index 0000000000..beb7e9f098 --- /dev/null +++ b/boost/python/converter/context_result_converter.hpp @@ -0,0 +1,17 @@ +// Copyright David Abrahams 2003. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef CONTEXT_RESULT_CONVERTER_DWA2003917_HPP +# define CONTEXT_RESULT_CONVERTER_DWA2003917_HPP + +namespace boost { namespace python { namespace converter { + +// A ResultConverter base class used to indicate that this result +// converter should be constructed with the original Python argument +// list. +struct context_result_converter {}; + +}}} // namespace boost::python::converter + +#endif // CONTEXT_RESULT_CONVERTER_DWA2003917_HPP diff --git a/boost/python/converter/convertible_function.hpp b/boost/python/converter/convertible_function.hpp new file mode 100644 index 0000000000..4b29fbb00b --- /dev/null +++ b/boost/python/converter/convertible_function.hpp @@ -0,0 +1,14 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef CONVERTIBLE_FUNCTION_DWA200278_HPP +# define CONVERTIBLE_FUNCTION_DWA200278_HPP + +namespace boost { namespace python { namespace converter { + +typedef void* (*convertible_function)(PyObject*); + +}}} // namespace boost::python::converter + +#endif // CONVERTIBLE_FUNCTION_DWA200278_HPP diff --git a/boost/python/converter/from_python.hpp b/boost/python/converter/from_python.hpp new file mode 100644 index 0000000000..b2f24b3519 --- /dev/null +++ b/boost/python/converter/from_python.hpp @@ -0,0 +1,41 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef FIND_FROM_PYTHON_DWA2002223_HPP +# define FIND_FROM_PYTHON_DWA2002223_HPP + +# include <boost/python/detail/prefix.hpp> +# include <boost/python/converter/rvalue_from_python_data.hpp> + +namespace boost { namespace python { namespace converter { + +struct registration; + + +BOOST_PYTHON_DECL void* get_lvalue_from_python( + PyObject* source, registration const&); + +BOOST_PYTHON_DECL bool implicit_rvalue_convertible_from_python( + PyObject* source, registration const&); + +BOOST_PYTHON_DECL rvalue_from_python_stage1_data rvalue_from_python_stage1( + PyObject* source, registration const&); + +BOOST_PYTHON_DECL void* rvalue_from_python_stage2( + PyObject* source, rvalue_from_python_stage1_data&, registration const&); + +BOOST_PYTHON_DECL void* rvalue_result_from_python( + PyObject*, rvalue_from_python_stage1_data&); + +BOOST_PYTHON_DECL void* reference_result_from_python(PyObject*, registration const&); +BOOST_PYTHON_DECL void* pointer_result_from_python(PyObject*, registration const&); + +BOOST_PYTHON_DECL void void_result_from_python(PyObject*); + +BOOST_PYTHON_DECL void throw_no_pointer_from_python(PyObject*, registration const&); +BOOST_PYTHON_DECL void throw_no_reference_from_python(PyObject*, registration const&); + +}}} // namespace boost::python::converter + +#endif // FIND_FROM_PYTHON_DWA2002223_HPP diff --git a/boost/python/converter/implicit.hpp b/boost/python/converter/implicit.hpp new file mode 100644 index 0000000000..8bbbfd5ac1 --- /dev/null +++ b/boost/python/converter/implicit.hpp @@ -0,0 +1,46 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef IMPLICIT_DWA2002326_HPP +# define IMPLICIT_DWA2002326_HPP + +# include <boost/python/converter/rvalue_from_python_data.hpp> +# include <boost/python/converter/registrations.hpp> +# include <boost/python/converter/registered.hpp> + +# include <boost/python/extract.hpp> + +namespace boost { namespace python { namespace converter { + +template <class Source, class Target> +struct implicit +{ + static void* convertible(PyObject* obj) + { + // Find a converter which can produce a Source 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 implicit_rvalue_convertible_from_python(obj, registered<Source>::converters) + ? obj : 0; + } + + static void construct(PyObject* obj, rvalue_from_python_stage1_data* data) + { + void* storage = ((rvalue_from_python_storage<Target>*)data)->storage.bytes; + + arg_from_python<Source> get_source(obj); + bool convertible = get_source.convertible(); + BOOST_VERIFY(convertible); + + new (storage) Target(get_source()); + + // record successful construction + data->convertible = storage; + } +}; + +}}} // namespace boost::python::converter + +#endif // IMPLICIT_DWA2002326_HPP diff --git a/boost/python/converter/obj_mgr_arg_from_python.hpp b/boost/python/converter/obj_mgr_arg_from_python.hpp new file mode 100644 index 0000000000..cd4e1e0ea8 --- /dev/null +++ b/boost/python/converter/obj_mgr_arg_from_python.hpp @@ -0,0 +1,121 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef OBJ_MGR_ARG_FROM_PYTHON_DWA2002628_HPP +# define OBJ_MGR_ARG_FROM_PYTHON_DWA2002628_HPP + +# include <boost/python/detail/prefix.hpp> +# include <boost/python/detail/referent_storage.hpp> +# include <boost/python/detail/destroy.hpp> +# include <boost/python/detail/construct.hpp> +# include <boost/python/converter/object_manager.hpp> +# include <boost/python/detail/raw_pyobject.hpp> +# include <boost/python/tag.hpp> + +// +// arg_from_python converters for Python type wrappers, to be used as +// base classes for specializations. +// +namespace boost { namespace python { namespace converter { + +template <class T> +struct object_manager_value_arg_from_python +{ + typedef T result_type; + + object_manager_value_arg_from_python(PyObject*); + bool convertible() const; + T operator()() const; + private: + PyObject* m_source; +}; + +// Used for converting reference-to-object-manager arguments from +// python. The process used here is a little bit odd. Upon +// construction, we build the object manager object in the m_result +// object, *forcing* it to accept the source Python object by casting +// its pointer to detail::borrowed_reference. This is supposed to +// bypass any type checking of the source object. The convertible +// check then extracts the owned object and checks it. If the check +// fails, nothing else in the program ever gets to touch this strange +// "forced" object. +template <class Ref> +struct object_manager_ref_arg_from_python +{ + typedef Ref result_type; + + object_manager_ref_arg_from_python(PyObject*); + bool convertible() const; + Ref operator()() const; + ~object_manager_ref_arg_from_python(); + private: + typename python::detail::referent_storage<Ref>::type m_result; +}; + +// +// implementations +// + +template <class T> +inline object_manager_value_arg_from_python<T>::object_manager_value_arg_from_python(PyObject* x) + : m_source(x) +{ +} + +template <class T> +inline bool object_manager_value_arg_from_python<T>::convertible() const +{ + return object_manager_traits<T>::check(m_source); +} + +template <class T> +inline T object_manager_value_arg_from_python<T>::operator()() const +{ + return T(python::detail::borrowed_reference(m_source)); +} + +template <class Ref> +inline object_manager_ref_arg_from_python<Ref>::object_manager_ref_arg_from_python(PyObject* x) +{ +# if defined(__EDG_VERSION__) && __EDG_VERSION__ <= 243 + // needed for warning suppression + python::detail::borrowed_reference x_ = python::detail::borrowed_reference(x); + python::detail::construct_referent<Ref>(&m_result.bytes, x_); +# else + python::detail::construct_referent<Ref>(&m_result.bytes, (python::detail::borrowed_reference)x); +# endif +} + +template <class Ref> +inline object_manager_ref_arg_from_python<Ref>::~object_manager_ref_arg_from_python() +{ + python::detail::destroy_referent<Ref>(this->m_result.bytes); +} + +namespace detail +{ + template <class T> + inline bool object_manager_ref_check(T const& x) + { + return object_manager_traits<T>::check(get_managed_object(x, tag)); + } +} + +template <class Ref> +inline bool object_manager_ref_arg_from_python<Ref>::convertible() const +{ + return detail::object_manager_ref_check( + python::detail::void_ptr_to_reference(this->m_result.bytes, (Ref(*)())0)); +} + +template <class Ref> +inline Ref object_manager_ref_arg_from_python<Ref>::operator()() const +{ + return python::detail::void_ptr_to_reference( + this->m_result.bytes, (Ref(*)())0); +} + +}}} // namespace boost::python::converter + +#endif // OBJ_MGR_ARG_FROM_PYTHON_DWA2002628_HPP diff --git a/boost/python/converter/object_manager.hpp b/boost/python/converter/object_manager.hpp new file mode 100644 index 0000000000..84e44d475b --- /dev/null +++ b/boost/python/converter/object_manager.hpp @@ -0,0 +1,230 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef OBJECT_MANAGER_DWA2002614_HPP +# define OBJECT_MANAGER_DWA2002614_HPP + +# include <boost/python/handle.hpp> +# include <boost/python/cast.hpp> +# include <boost/python/converter/pyobject_traits.hpp> +# include <boost/type_traits/object_traits.hpp> +# include <boost/mpl/if.hpp> +# include <boost/python/detail/indirect_traits.hpp> +# include <boost/mpl/bool.hpp> + +// Facilities for dealing with types which always manage Python +// objects. Some examples are object, list, str, et. al. Different +// to_python/from_python conversion rules apply here because in +// contrast to other types which are typically embedded inside a +// Python object, these are wrapped around a Python object. For most +// object managers T, a C++ non-const T reference argument does not +// imply the existence of a T lvalue embedded in the corresponding +// Python argument, since mutating member functions on T actually only +// modify the held Python object. +// +// handle<T> is an object manager, though strictly speaking it should +// not be. In other words, even though mutating member functions of +// hanlde<T> actually modify the handle<T> and not the T object, +// handle<T>& arguments of wrapped functions will bind to "rvalues" +// wrapping the actual Python argument, just as with other object +// manager classes. Making an exception for handle<T> is simply not +// worth the trouble. +// +// borrowed<T> cv* is an object manager so that we can use the general +// to_python mechanisms to convert raw Python object pointers to +// python, without the usual semantic problems of using raw pointers. + + +// Object Manager Concept requirements: +// +// T is an Object Manager +// p is a PyObject* +// x is a T +// +// * object_manager_traits<T>::is_specialized == true +// +// * T(detail::borrowed_reference(p)) +// Manages p without checking its type +// +// * get_managed_object(x, boost::python::tag) +// Convertible to PyObject* +// +// Additional requirements if T can be converted from_python: +// +// * T(object_manager_traits<T>::adopt(p)) +// steals a reference to p, or throws a TypeError exception if +// p doesn't have an appropriate type. May assume p is non-null +// +// * X::check(p) +// convertible to bool. True iff T(X::construct(p)) will not +// throw. + +// Forward declarations +// +namespace boost { namespace python +{ + namespace api + { + class object; + } +}} + +namespace boost { namespace python { namespace converter { + + +// Specializations for handle<T> +template <class T> +struct handle_object_manager_traits + : pyobject_traits<typename T::element_type> +{ + private: + typedef pyobject_traits<typename T::element_type> base; + + public: + BOOST_STATIC_CONSTANT(bool, is_specialized = true); + + // Initialize with a null_ok pointer for efficiency, bypassing the + // null check since the source is always non-null. + static null_ok<typename T::element_type>* adopt(PyObject* p) + { + return python::allow_null(base::checked_downcast(p)); + } +}; + +template <class T> +struct default_object_manager_traits +{ + BOOST_STATIC_CONSTANT( + bool, is_specialized = python::detail::is_borrowed_ptr<T>::value + ); +}; + +template <class T> +struct object_manager_traits + : mpl::if_c< + is_handle<T>::value + , handle_object_manager_traits<T> + , default_object_manager_traits<T> + >::type +{ +}; + +// +// Traits for detecting whether a type is an object manager or a +// (cv-qualified) reference to an object manager. +// + +template <class T> +struct is_object_manager + : mpl::bool_<object_manager_traits<T>::is_specialized> +{ +}; + +# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +template <class T> +struct is_reference_to_object_manager + : mpl::false_ +{ +}; + +template <class T> +struct is_reference_to_object_manager<T&> + : is_object_manager<T> +{ +}; + +template <class T> +struct is_reference_to_object_manager<T const&> + : is_object_manager<T> +{ +}; + +template <class T> +struct is_reference_to_object_manager<T volatile&> + : is_object_manager<T> +{ +}; + +template <class T> +struct is_reference_to_object_manager<T const volatile&> + : is_object_manager<T> +{ +}; +# else + +namespace detail +{ + typedef char (&yes_reference_to_object_manager)[1]; + typedef char (&no_reference_to_object_manager)[2]; + + // A number of nastinesses go on here in order to work around MSVC6 + // bugs. + template <class T> + struct is_object_manager_help + { + typedef typename mpl::if_< + is_object_manager<T> + , yes_reference_to_object_manager + , no_reference_to_object_manager + >::type type; + + // If we just use the type instead of the result of calling this + // function, VC6 will ICE. + static type call(); + }; + + // A set of overloads for each cv-qualification. The same argument + // is passed twice: the first one is used to unwind the cv*, and the + // second one is used to avoid relying on partial ordering for + // overload resolution. + template <class U> + typename is_object_manager_help<U> + is_object_manager_helper(U*, void*); + + template <class U> + typename is_object_manager_help<U> + is_object_manager_helper(U const*, void const*); + + template <class U> + typename is_object_manager_help<U> + is_object_manager_helper(U volatile*, void volatile*); + + template <class U> + typename is_object_manager_help<U> + is_object_manager_helper(U const volatile*, void const volatile*); + + template <class T> + struct is_reference_to_object_manager_nonref + : mpl::false_ + { + }; + + template <class T> + struct is_reference_to_object_manager_ref + { + static T sample_object; + BOOST_STATIC_CONSTANT( + bool, value + = (sizeof(is_object_manager_helper(&sample_object, &sample_object).call()) + == sizeof(detail::yes_reference_to_object_manager) + ) + ); + typedef mpl::bool_<value> type; + }; +} + +template <class T> +struct is_reference_to_object_manager + : mpl::if_< + is_reference<T> + , detail::is_reference_to_object_manager_ref<T> + , detail::is_reference_to_object_manager_nonref<T> + >::type +{ +}; +# endif + +}}} // namespace boost::python::converter + +#endif // OBJECT_MANAGER_DWA2002614_HPP diff --git a/boost/python/converter/pointer_type_id.hpp b/boost/python/converter/pointer_type_id.hpp new file mode 100644 index 0000000000..963f58f717 --- /dev/null +++ b/boost/python/converter/pointer_type_id.hpp @@ -0,0 +1,68 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef POINTER_TYPE_ID_DWA2002222_HPP +# define POINTER_TYPE_ID_DWA2002222_HPP + +# include <boost/python/type_id.hpp> +# include <boost/type_traits/composite_traits.hpp> + +namespace boost { namespace python { namespace converter { + +namespace detail +{ + template <bool is_ref = false> + struct pointer_typeid_select + { + template <class T> + static inline type_info execute(T*(*)() = 0) + { + return type_id<T>(); + } + }; + + template <> + struct pointer_typeid_select<true> + { + template <class T> + static inline type_info execute(T* const volatile&(*)() = 0) + { + return type_id<T>(); + } + + template <class T> + static inline type_info execute(T*volatile&(*)() = 0) + { + return type_id<T>(); + } + + template <class T> + static inline type_info execute(T*const&(*)() = 0) + { + return type_id<T>(); + } + + template <class T> + static inline type_info execute(T*&(*)() = 0) + { + return type_id<T>(); + } + }; +} + +// Usage: pointer_type_id<T>() +// +// Returns a type_info associated with the type pointed +// to by T, which may be a pointer or a reference to a pointer. +template <class T> +type_info pointer_type_id(T(*)() = 0) +{ + return detail::pointer_typeid_select< + is_reference<T>::value + >::execute((T(*)())0); +} + +}}} // namespace boost::python::converter + +#endif // POINTER_TYPE_ID_DWA2002222_HPP diff --git a/boost/python/converter/pyobject_traits.hpp b/boost/python/converter/pyobject_traits.hpp new file mode 100644 index 0000000000..43e384af8d --- /dev/null +++ b/boost/python/converter/pyobject_traits.hpp @@ -0,0 +1,46 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef PYOBJECT_TRAITS_DWA2002720_HPP +# define PYOBJECT_TRAITS_DWA2002720_HPP + +# include <boost/python/detail/prefix.hpp> +# include <boost/python/converter/pyobject_type.hpp> + +namespace boost { namespace python { namespace converter { + +template <class> struct pyobject_traits; + +template <> +struct pyobject_traits<PyObject> +{ + // All objects are convertible to PyObject + static bool check(PyObject*) { return true; } + static PyObject* checked_downcast(PyObject* x) { return x; } +#ifndef BOOST_PYTHON_NO_PY_SIGNATURES + static PyTypeObject const* get_pytype() { return 0; } +#endif +}; + +// +// Specializations +// + +# define BOOST_PYTHON_BUILTIN_OBJECT_TRAITS(T) \ + template <> struct pyobject_traits<Py##T##Object> \ + : pyobject_type<Py##T##Object, &Py##T##_Type> {} + +// This is not an exhaustive list; should be expanded. +BOOST_PYTHON_BUILTIN_OBJECT_TRAITS(Type); +BOOST_PYTHON_BUILTIN_OBJECT_TRAITS(List); +#if PY_VERSION_HEX < 0x03000000 +BOOST_PYTHON_BUILTIN_OBJECT_TRAITS(Int); +#endif +BOOST_PYTHON_BUILTIN_OBJECT_TRAITS(Long); +BOOST_PYTHON_BUILTIN_OBJECT_TRAITS(Dict); +BOOST_PYTHON_BUILTIN_OBJECT_TRAITS(Tuple); + +}}} // namespace boost::python::converter + +#endif // PYOBJECT_TRAITS_DWA2002720_HPP diff --git a/boost/python/converter/pyobject_type.hpp b/boost/python/converter/pyobject_type.hpp new file mode 100644 index 0000000000..526f9f9dba --- /dev/null +++ b/boost/python/converter/pyobject_type.hpp @@ -0,0 +1,37 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef PYOBJECT_TYPE_DWA2002720_HPP +# define PYOBJECT_TYPE_DWA2002720_HPP + +# include <boost/python/cast.hpp> + +namespace boost { namespace python { namespace converter { + +BOOST_PYTHON_DECL PyObject* checked_downcast_impl(PyObject*, PyTypeObject*); + +// Used as a base class for specializations which need to provide +// Python type checking capability. +template <class Object, PyTypeObject* pytype> +struct pyobject_type +{ + static bool check(PyObject* x) + { + return ::PyObject_IsInstance(x, (PyObject*)pytype); + } + + static Object* checked_downcast(PyObject* x) + { + return python::downcast<Object>( + (checked_downcast_impl)(x, pytype) + ); + } +#ifndef BOOST_PYTHON_NO_PY_SIGNATURES + static PyTypeObject const* get_pytype() { return pytype; } +#endif +}; + +}}} // namespace boost::python::converter + +#endif // PYOBJECT_TYPE_DWA2002720_HPP diff --git a/boost/python/converter/pytype_function.hpp b/boost/python/converter/pytype_function.hpp new file mode 100644 index 0000000000..95d0f66d46 --- /dev/null +++ b/boost/python/converter/pytype_function.hpp @@ -0,0 +1,132 @@ +// Copyright David Abrahams 2002, Nikolay Mladenov 2007. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef WRAP_PYTYPE_NM20070606_HPP +# define WRAP_PYTYPE_NM20070606_HPP + +# include <boost/python/detail/prefix.hpp> +# include <boost/python/converter/registered.hpp> +# include <boost/python/detail/unwind_type.hpp> + + +namespace boost { namespace python { + +namespace converter +{ +template <PyTypeObject const* python_type> +struct wrap_pytype +{ + static PyTypeObject const* get_pytype() + { + return python_type; + } +}; + +typedef PyTypeObject const* (*pytype_function)(); + +#ifndef BOOST_PYTHON_NO_PY_SIGNATURES + + + +namespace detail +{ +struct unwind_type_id_helper{ + typedef python::type_info result_type; + template <class U> + static result_type execute(U* ){ + return python::type_id<U>(); + } +}; + +template <class T> +inline python::type_info unwind_type_id_(boost::type<T>* = 0, mpl::false_ * =0) +{ + return boost::python::detail::unwind_type<unwind_type_id_helper, T> (); +} + +inline python::type_info unwind_type_id_(boost::type<void>* = 0, mpl::true_* =0) +{ + return type_id<void>(); +} + +template <class T> +inline python::type_info unwind_type_id(boost::type<T>* p= 0) +{ + return unwind_type_id_(p, (mpl::bool_<boost::is_void<T>::value >*)0 ); +} +} + + +template <class T> +struct expected_pytype_for_arg +{ + static PyTypeObject const *get_pytype() + { + const converter::registration *r=converter::registry::query( + detail::unwind_type_id_((boost::type<T>*)0, (mpl::bool_<boost::is_void<T>::value >*)0 ) + ); + return r ? r->expected_from_python_type(): 0; + } +}; + + +template <class T> +struct registered_pytype +{ + static PyTypeObject const *get_pytype() + { + const converter::registration *r=converter::registry::query( + detail::unwind_type_id_((boost::type<T>*) 0, (mpl::bool_<boost::is_void<T>::value >*)0 ) + ); + return r ? r->m_class_object: 0; + } +}; + + +template <class T> +struct registered_pytype_direct +{ + static PyTypeObject const* get_pytype() + { + return registered<T>::converters.m_class_object; + } +}; + +template <class T> +struct expected_from_python_type : expected_pytype_for_arg<T>{}; + +template <class T> +struct expected_from_python_type_direct +{ + static PyTypeObject const* get_pytype() + { + return registered<T>::converters.expected_from_python_type(); + } +}; + +template <class T> +struct to_python_target_type +{ + static PyTypeObject const *get_pytype() + { + const converter::registration *r=converter::registry::query( + detail::unwind_type_id_((boost::type<T>*)0, (mpl::bool_<boost::is_void<T>::value >*)0 ) + ); + return r ? r->to_python_target_type(): 0; + } +}; + +template <class T> +struct to_python_target_type_direct +{ + static PyTypeObject const *get_pytype() + { + return registered<T>::converters.to_python_target_type(); + } +}; +#endif + +}}} // namespace boost::python + +#endif // WRAP_PYTYPE_NM20070606_HPP diff --git a/boost/python/converter/pytype_object_mgr_traits.hpp b/boost/python/converter/pytype_object_mgr_traits.hpp new file mode 100644 index 0000000000..8f5b2b7677 --- /dev/null +++ b/boost/python/converter/pytype_object_mgr_traits.hpp @@ -0,0 +1,42 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef PYTYPE_OBJECT_MANAGER_TRAITS_DWA2002716_HPP +# define PYTYPE_OBJECT_MANAGER_TRAITS_DWA2002716_HPP + +# include <boost/python/detail/prefix.hpp> +# include <boost/python/detail/raw_pyobject.hpp> +# include <boost/python/cast.hpp> +# include <boost/python/converter/pyobject_type.hpp> +# include <boost/python/errors.hpp> + +namespace boost { namespace python { namespace converter { + +// Provide a forward declaration as a convenience for clients, who all +// need it. +template <class T> struct object_manager_traits; + +// Derive specializations of object_manager_traits from this class +// when T is an object manager for a particular Python type hierarchy. +// +template <PyTypeObject* pytype, class T> +struct pytype_object_manager_traits + : pyobject_type<T, pytype> // provides check() +{ + BOOST_STATIC_CONSTANT(bool, is_specialized = true); + static inline python::detail::new_reference adopt(PyObject*); +}; + +// +// implementations +// +template <PyTypeObject* pytype, class T> +inline python::detail::new_reference pytype_object_manager_traits<pytype,T>::adopt(PyObject* x) +{ + return python::detail::new_reference(python::pytype_check(pytype, x)); +} + +}}} // namespace boost::python::converter + +#endif // PYTYPE_OBJECT_MANAGER_TRAITS_DWA2002716_HPP diff --git a/boost/python/converter/registered.hpp b/boost/python/converter/registered.hpp new file mode 100644 index 0000000000..2404cb0ff2 --- /dev/null +++ b/boost/python/converter/registered.hpp @@ -0,0 +1,111 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef REGISTERED_DWA2002710_HPP +# define REGISTERED_DWA2002710_HPP +# include <boost/python/type_id.hpp> +# include <boost/python/converter/registry.hpp> +# include <boost/python/converter/registrations.hpp> +# include <boost/type_traits/transform_traits.hpp> +# include <boost/type_traits/cv_traits.hpp> +# include <boost/type_traits/is_void.hpp> +# include <boost/detail/workaround.hpp> +# include <boost/python/type_id.hpp> +# include <boost/type.hpp> + +namespace boost { + +// You'll see shared_ptr mentioned in this header because we need to +// note which types are shared_ptrs in their registrations, to +// implement special shared_ptr handling for rvalue conversions. +template <class T> class shared_ptr; + +namespace python { namespace converter { + +struct registration; + +namespace detail +{ + template <class T> + struct registered_base + { + static registration const& converters; + }; +} + +template <class T> +struct registered + : detail::registered_base< + typename add_reference< + typename add_cv<T>::type + >::type + > +{ +}; + +# if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) \ + && !BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1310)) +// collapses a few more types to the same static instance. MSVC7.1 +// fails to strip cv-qualification from array types in typeid. For +// some reason we can't use this collapse there or array converters +// will not be found. +template <class T> +struct registered<T&> + : registered<T> {}; +# endif + +// +// implementations +// +namespace detail +{ + inline void + register_shared_ptr0(...) + { + } + + template <class T> + inline void + register_shared_ptr0(shared_ptr<T>*) + { + registry::lookup_shared_ptr(type_id<shared_ptr<T> >()); + } + + template <class T> + inline void + register_shared_ptr1(T const volatile*) + { + detail::register_shared_ptr0((T*)0); + } + + template <class T> + inline registration const& + registry_lookup2(T&(*)()) + { + detail::register_shared_ptr1((T*)0); + return registry::lookup(type_id<T&>()); + } + + template <class T> + inline registration const& + registry_lookup1(type<T>) + { + return registry_lookup2((T(*)())0); + } + + inline registration const& + registry_lookup1(type<const volatile void>) + { + detail::register_shared_ptr1((void*)0); + return registry::lookup(type_id<void>()); + } + + template <class T> + registration const& registered_base<T>::converters = detail::registry_lookup1(type<T>()); + +} + +}}} // namespace boost::python::converter + +#endif // REGISTERED_DWA2002710_HPP diff --git a/boost/python/converter/registered_pointee.hpp b/boost/python/converter/registered_pointee.hpp new file mode 100644 index 0000000000..d9e7ac75a8 --- /dev/null +++ b/boost/python/converter/registered_pointee.hpp @@ -0,0 +1,62 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef REGISTERED_POINTEE_DWA2002710_HPP +# define REGISTERED_POINTEE_DWA2002710_HPP +# include <boost/python/converter/registered.hpp> +# include <boost/python/converter/pointer_type_id.hpp> +# include <boost/python/converter/registry.hpp> +# include <boost/type_traits/transform_traits.hpp> +# include <boost/type_traits/cv_traits.hpp> + +namespace boost { namespace python { namespace converter { + +struct registration; + +# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +template <class T> +struct registered_pointee + : registered< + typename remove_pointer< + typename remove_cv< + typename remove_reference<T>::type + >::type + >::type + > +{ +}; +# else +namespace detail +{ + template <class T> + struct registered_pointee_base + { + static registration const& converters; + }; +} + +template <class T> +struct registered_pointee + : detail::registered_pointee_base< + typename add_reference< + typename add_cv<T>::type + >::type + > +{ +}; + +// +// implementations +// +namespace detail +{ + template <class T> + registration const& registered_pointee_base<T>::converters + = registry::lookup(pointer_type_id<T>()); +} + +# endif +}}} // namespace boost::python::converter + +#endif // REGISTERED_POINTEE_DWA2002710_HPP diff --git a/boost/python/converter/registrations.hpp b/boost/python/converter/registrations.hpp new file mode 100644 index 0000000000..7ef74e8f40 --- /dev/null +++ b/boost/python/converter/registrations.hpp @@ -0,0 +1,99 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef REGISTRATIONS_DWA2002223_HPP +# define REGISTRATIONS_DWA2002223_HPP + +# include <boost/python/detail/prefix.hpp> + +# include <boost/python/type_id.hpp> + +# include <boost/python/converter/convertible_function.hpp> +# include <boost/python/converter/constructor_function.hpp> +# include <boost/python/converter/to_python_function_type.hpp> + +# include <boost/detail/workaround.hpp> + +namespace boost { namespace python { namespace converter { + +struct lvalue_from_python_chain +{ + convertible_function convert; + lvalue_from_python_chain* next; +}; + +struct rvalue_from_python_chain +{ + convertible_function convertible; + constructor_function construct; + PyTypeObject const* (*expected_pytype)(); + rvalue_from_python_chain* next; +}; + +struct BOOST_PYTHON_DECL registration +{ + public: // member functions + explicit registration(type_info target, bool is_shared_ptr = false); + ~registration(); + + // Convert the appropriately-typed data to Python + PyObject* to_python(void const volatile*) const; + + // Return the class object, or raise an appropriate Python + // exception if no class has been registered. + PyTypeObject* get_class_object() const; + + // Return common denominator of the python class objects, + // convertable to target. Inspects the m_class_object and the value_chains. + PyTypeObject const* expected_from_python_type() const; + PyTypeObject const* to_python_target_type() const; + + public: // data members. So sue me. + const python::type_info target_type; + + // The chain of eligible from_python converters when an lvalue is required + lvalue_from_python_chain* lvalue_chain; + + // The chain of eligible from_python converters when an rvalue is acceptable + rvalue_from_python_chain* rvalue_chain; + + // The class object associated with this type + PyTypeObject* m_class_object; + + // The unique to_python converter for the associated C++ type. + to_python_function_t m_to_python; + PyTypeObject const* (*m_to_python_target_type)(); + + + // True iff this type is a shared_ptr. Needed for special rvalue + // from_python handling. + const bool is_shared_ptr; + +# if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003)) + private: + void operator=(registration); // This is not defined, and just keeps MWCW happy. +# endif +}; + +// +// implementations +// +inline registration::registration(type_info target_type, bool is_shared_ptr) + : target_type(target_type) + , lvalue_chain(0) + , rvalue_chain(0) + , m_class_object(0) + , m_to_python(0) + , m_to_python_target_type(0) + , is_shared_ptr(is_shared_ptr) +{} + +inline bool operator<(registration const& lhs, registration const& rhs) +{ + return lhs.target_type < rhs.target_type; +} + +}}} // namespace boost::python::converter + +#endif // REGISTRATIONS_DWA2002223_HPP diff --git a/boost/python/converter/registry.hpp b/boost/python/converter/registry.hpp new file mode 100644 index 0000000000..368adcc61d --- /dev/null +++ b/boost/python/converter/registry.hpp @@ -0,0 +1,55 @@ +// Copyright David Abrahams 2001. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef REGISTRY_DWA20011127_HPP +# define REGISTRY_DWA20011127_HPP +# include <boost/python/type_id.hpp> +# include <boost/python/converter/to_python_function_type.hpp> +# include <boost/python/converter/rvalue_from_python_data.hpp> +# include <boost/python/converter/constructor_function.hpp> +# include <boost/python/converter/convertible_function.hpp> + +namespace boost { namespace python { namespace converter { + +struct registration; + +// This namespace acts as a sort of singleton +namespace registry +{ + // Get the registration corresponding to the type, creating it if necessary + BOOST_PYTHON_DECL registration const& lookup(type_info); + + // Get the registration corresponding to the type, creating it if + // necessary. Use this first when the type is a shared_ptr. + BOOST_PYTHON_DECL registration const& lookup_shared_ptr(type_info); + + // Return a pointer to the corresponding registration, if one exists + BOOST_PYTHON_DECL registration const* query(type_info); + + BOOST_PYTHON_DECL void insert(to_python_function_t, type_info, PyTypeObject const* (*to_python_target_type)() = 0); + + // Insert an lvalue from_python converter + BOOST_PYTHON_DECL void insert(convertible_function, type_info, PyTypeObject const* (*expected_pytype)() = 0); + + // Insert an rvalue from_python converter + BOOST_PYTHON_DECL void insert( + convertible_function + , constructor_function + , type_info + , PyTypeObject const* (*expected_pytype)() = 0 + ); + + // Insert an rvalue from_python converter at the tail of the + // chain. Used for implicit conversions + BOOST_PYTHON_DECL void push_back( + convertible_function + , constructor_function + , type_info + , PyTypeObject const* (*expected_pytype)() = 0 + ); +} + +}}} // namespace boost::python::converter + +#endif // REGISTRY_DWA20011127_HPP diff --git a/boost/python/converter/return_from_python.hpp b/boost/python/converter/return_from_python.hpp new file mode 100644 index 0000000000..5db9748545 --- /dev/null +++ b/boost/python/converter/return_from_python.hpp @@ -0,0 +1,162 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef RETURN_FROM_PYTHON_DWA200265_HPP +# define RETURN_FROM_PYTHON_DWA200265_HPP + +# include <boost/python/converter/from_python.hpp> +# include <boost/python/converter/rvalue_from_python_data.hpp> +# include <boost/python/converter/registered.hpp> +# include <boost/python/converter/registered_pointee.hpp> +# include <boost/python/converter/object_manager.hpp> +# include <boost/python/detail/void_ptr.hpp> +# include <boost/python/detail/void_return.hpp> +# include <boost/python/errors.hpp> +# include <boost/python/handle.hpp> +# include <boost/type_traits/has_trivial_copy.hpp> +# include <boost/mpl/and.hpp> +# include <boost/mpl/bool.hpp> + +namespace boost { namespace python { namespace converter { + +template <class T> struct is_object_manager; + +namespace detail +{ + template <class T> + struct return_pointer_from_python + { + typedef T result_type; + T operator()(PyObject*) const; + }; + + template <class T> + struct return_reference_from_python + { + typedef T result_type; + T operator()(PyObject*) const; + }; + + template <class T> + struct return_rvalue_from_python + { + typedef T result_type; + + return_rvalue_from_python(); + result_type operator()(PyObject*); + private: + rvalue_from_python_data<T> m_data; + }; + + template <class T> + struct return_object_manager_from_python + { + typedef T result_type; + result_type operator()(PyObject*) const; + }; + + template <class T> + struct select_return_from_python + { + BOOST_STATIC_CONSTANT( + bool, obj_mgr = is_object_manager<T>::value); + + BOOST_STATIC_CONSTANT( + bool, ptr = is_pointer<T>::value); + + BOOST_STATIC_CONSTANT( + bool, ref = is_reference<T>::value); + + typedef typename mpl::if_c< + obj_mgr + , return_object_manager_from_python<T> + , typename mpl::if_c< + ptr + , return_pointer_from_python<T> + , typename mpl::if_c< + ref + , return_reference_from_python<T> + , return_rvalue_from_python<T> + >::type + >::type + >::type type; + }; +} + +template <class T> +struct return_from_python + : detail::select_return_from_python<T>::type +{ +}; + +// Specialization as a convenience for call and call_method +template <> +struct return_from_python<void> +{ + typedef python::detail::returnable<void>::type result_type; + + result_type operator()(PyObject* x) const + { + (void_result_from_python)(x); +# ifdef BOOST_NO_VOID_RETURNS + return result_type(); +# endif + } +}; + +// +// Implementations +// +namespace detail +{ + template <class T> + inline return_rvalue_from_python<T>::return_rvalue_from_python() + : m_data( + const_cast<registration*>(®istered<T>::converters) + ) + { + } + + template <class T> + inline typename return_rvalue_from_python<T>::result_type + return_rvalue_from_python<T>::operator()(PyObject* obj) + { + // Take possession of the source object here. If the result is in + // fact going to be a copy of an lvalue embedded in the object, + // and we take possession inside rvalue_result_from_python, it + // will be destroyed too early. + handle<> holder(obj); + + return *(T*) + (rvalue_result_from_python)(obj, m_data.stage1); + } + + template <class T> + inline T return_reference_from_python<T>::operator()(PyObject* obj) const + { + return python::detail::void_ptr_to_reference( + (reference_result_from_python)(obj, registered<T>::converters) + , (T(*)())0); + } + + template <class T> + inline T return_pointer_from_python<T>::operator()(PyObject* obj) const + { + return T( + (pointer_result_from_python)(obj, registered_pointee<T>::converters) + ); + } + + template <class T> + inline T return_object_manager_from_python<T>::operator()(PyObject* obj) const + { + return T( + object_manager_traits<T>::adopt(expect_non_null(obj)) + ); + } +} + +}}} // namespace boost::python::converter + +#endif // RETURN_FROM_PYTHON_DWA200265_HPP diff --git a/boost/python/converter/rvalue_from_python_data.hpp b/boost/python/converter/rvalue_from_python_data.hpp new file mode 100644 index 0000000000..471a5255b6 --- /dev/null +++ b/boost/python/converter/rvalue_from_python_data.hpp @@ -0,0 +1,140 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef FROM_PYTHON_AUX_DATA_DWA2002128_HPP +# define FROM_PYTHON_AUX_DATA_DWA2002128_HPP + +# include <boost/python/converter/constructor_function.hpp> +# include <boost/python/detail/referent_storage.hpp> +# include <boost/python/detail/destroy.hpp> +# include <boost/static_assert.hpp> +# include <boost/type_traits/add_reference.hpp> +# include <boost/type_traits/add_cv.hpp> +# include <cstddef> + +// Data management for potential rvalue conversions from Python to C++ +// types. When a client requests a conversion to T* or T&, we +// generally require that an object of type T exists in the source +// Python object, and the code here does not apply**. This implements +// conversions which may create new temporaries of type T. The classic +// example is a conversion which converts a Python tuple to a +// std::vector. Since no std::vector lvalue exists in the Python +// object -- it must be created "on-the-fly" by the converter, and +// which must manage the lifetime of the created object. +// +// Note that the client is not precluded from using a registered +// lvalue conversion to T in this case. In other words, we will +// happily accept a Python object which /does/ contain a std::vector +// lvalue, provided an appropriate converter is registered. So, while +// this is an rvalue conversion from the client's point-of-view, the +// converter registry may serve up lvalue or rvalue conversions for +// the target type. +// +// ** C++ argument from_python conversions to T const& are an +// exception to the rule for references: since in C++, const +// references can bind to temporary rvalues, we allow rvalue +// converters to be chosen when the target type is T const& for some +// T. +namespace boost { namespace python { namespace converter { + +// Conversions begin by filling in and returning a copy of this +// structure. The process looks up a converter in the rvalue converter +// registry for the target type. It calls the convertible() function +// of each registered converter, passing the source PyObject* as an +// argument, until a non-null result is returned. This result goes in +// the convertible field, and the converter's construct() function is +// stored in the construct field. +// +// If no appropriate converter is found, conversion fails and the +// convertible field is null. When used in argument conversion for +// wrapped C++ functions, it causes overload resolution to reject the +// current function but not to fail completely. If an exception is +// thrown, overload resolution stops and the exception propagates back +// through the caller. +// +// If an lvalue converter is matched, its convertible() function is +// expected to return a pointer to the stored T object; its +// construct() function will be NULL. The convertible() function of +// rvalue converters may return any non-singular pointer; the actual +// target object will only be available once the converter's +// construct() function is called. +struct rvalue_from_python_stage1_data +{ + void* convertible; + constructor_function construct; +}; + +// Augments rvalue_from_python_stage1_data by adding storage for +// constructing an object of remove_reference<T>::type. The +// construct() function of rvalue converters (stored in m_construct +// above) will cast the rvalue_from_python_stage1_data to an +// appropriate instantiation of this template in order to access that +// storage. +template <class T> +struct rvalue_from_python_storage +{ + rvalue_from_python_stage1_data stage1; + + // Storage for the result, in case an rvalue must be constructed + typename python::detail::referent_storage< + typename add_reference<T>::type + >::type storage; +}; + +// Augments rvalue_from_python_storage<T> with a destructor. If +// stage1.convertible == storage.bytes, it indicates that an object of +// remove_reference<T>::type has been constructed in storage and +// should will be destroyed in ~rvalue_from_python_data(). It is +// crucial that successful rvalue conversions establish this equality +// and that unsuccessful ones do not. +template <class T> +struct rvalue_from_python_data : rvalue_from_python_storage<T> +{ +# if (!defined(__MWERKS__) || __MWERKS__ >= 0x3000) \ + && (!defined(__EDG_VERSION__) || __EDG_VERSION__ >= 245) \ + && (!defined(__DECCXX_VER) || __DECCXX_VER > 60590014) \ + && !defined(BOOST_PYTHON_SYNOPSIS) /* Synopsis' OpenCXX has trouble parsing this */ + // This must always be a POD struct with m_data its first member. + BOOST_STATIC_ASSERT(BOOST_PYTHON_OFFSETOF(rvalue_from_python_storage<T>,stage1) == 0); +# endif + + // The usual constructor + rvalue_from_python_data(rvalue_from_python_stage1_data const&); + + // This constructor just sets m_convertible -- used by + // implicitly_convertible<> to perform the final step of the + // conversion, where the construct() function is already known. + rvalue_from_python_data(void* convertible); + + // Destroys any object constructed in the storage. + ~rvalue_from_python_data(); + private: + typedef typename add_reference<typename add_cv<T>::type>::type ref_type; +}; + +// +// Implementataions +// +template <class T> +inline rvalue_from_python_data<T>::rvalue_from_python_data(rvalue_from_python_stage1_data const& _stage1) +{ + this->stage1 = _stage1; +} + +template <class T> +inline rvalue_from_python_data<T>::rvalue_from_python_data(void* convertible) +{ + this->stage1.convertible = convertible; +} + +template <class T> +inline rvalue_from_python_data<T>::~rvalue_from_python_data() +{ + if (this->stage1.convertible == this->storage.bytes) + python::detail::destroy_referent<ref_type>(this->storage.bytes); +} + +}}} // namespace boost::python::converter + +#endif // FROM_PYTHON_AUX_DATA_DWA2002128_HPP diff --git a/boost/python/converter/shared_ptr_deleter.hpp b/boost/python/converter/shared_ptr_deleter.hpp new file mode 100644 index 0000000000..926508d00e --- /dev/null +++ b/boost/python/converter/shared_ptr_deleter.hpp @@ -0,0 +1,22 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef SHARED_PTR_DELETER_DWA2002121_HPP +# define SHARED_PTR_DELETER_DWA2002121_HPP + +namespace boost { namespace python { namespace converter { + +struct BOOST_PYTHON_DECL shared_ptr_deleter +{ + shared_ptr_deleter(handle<> owner); + ~shared_ptr_deleter(); + + void operator()(void const*); + + handle<> owner; +}; + +}}} // namespace boost::python::converter + +#endif // SHARED_PTR_DELETER_DWA2002121_HPP diff --git a/boost/python/converter/shared_ptr_from_python.hpp b/boost/python/converter/shared_ptr_from_python.hpp new file mode 100644 index 0000000000..c09107765c --- /dev/null +++ b/boost/python/converter/shared_ptr_from_python.hpp @@ -0,0 +1,63 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef SHARED_PTR_FROM_PYTHON_DWA20021130_HPP +# define SHARED_PTR_FROM_PYTHON_DWA20021130_HPP + +# include <boost/python/handle.hpp> +# include <boost/python/converter/shared_ptr_deleter.hpp> +# include <boost/python/converter/from_python.hpp> +# include <boost/python/converter/rvalue_from_python_data.hpp> +# include <boost/python/converter/registered.hpp> +#ifndef BOOST_PYTHON_NO_PY_SIGNATURES +# include <boost/python/converter/pytype_function.hpp> +#endif +# include <boost/shared_ptr.hpp> + +namespace boost { namespace python { namespace converter { + +template <class T> +struct shared_ptr_from_python +{ + shared_ptr_from_python() + { + converter::registry::insert(&convertible, &construct, type_id<shared_ptr<T> >() +#ifndef BOOST_PYTHON_NO_PY_SIGNATURES + , &converter::expected_from_python_type_direct<T>::get_pytype +#endif + ); + } + + private: + static void* convertible(PyObject* p) + { + if (p == Py_None) + return p; + + return converter::get_lvalue_from_python(p, registered<T>::converters); + } + + static void construct(PyObject* source, rvalue_from_python_stage1_data* data) + { + void* const storage = ((converter::rvalue_from_python_storage<shared_ptr<T> >*)data)->storage.bytes; + // Deal with the "None" case. + if (data->convertible == source) + new (storage) shared_ptr<T>(); + else + { + boost::shared_ptr<void> hold_convertible_ref_count( + (void*)0, shared_ptr_deleter(handle<>(borrowed(source))) ); + // use aliasing constructor + new (storage) shared_ptr<T>( + hold_convertible_ref_count, + static_cast<T*>(data->convertible)); + } + + data->convertible = storage; + } +}; + +}}} // namespace boost::python::converter + +#endif // SHARED_PTR_FROM_PYTHON_DWA20021130_HPP diff --git a/boost/python/converter/shared_ptr_to_python.hpp b/boost/python/converter/shared_ptr_to_python.hpp new file mode 100644 index 0000000000..fe867ace13 --- /dev/null +++ b/boost/python/converter/shared_ptr_to_python.hpp @@ -0,0 +1,28 @@ +// Copyright David Abrahams 2003. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef SHARED_PTR_TO_PYTHON_DWA2003224_HPP +# define SHARED_PTR_TO_PYTHON_DWA2003224_HPP + +# include <boost/python/refcount.hpp> +# include <boost/python/converter/shared_ptr_deleter.hpp> +# include <boost/shared_ptr.hpp> +# include <boost/get_pointer.hpp> + +namespace boost { namespace python { namespace converter { + +template <class T> +PyObject* shared_ptr_to_python(shared_ptr<T> const& x) +{ + if (!x) + return python::detail::none(); + else if (shared_ptr_deleter* d = boost::get_deleter<shared_ptr_deleter>(x)) + return incref( get_pointer( d->owner ) ); + else + return converter::registered<shared_ptr<T> const&>::converters.to_python(&x); +} + +}}} // namespace boost::python::converter + +#endif // SHARED_PTR_TO_PYTHON_DWA2003224_HPP diff --git a/boost/python/converter/to_python_function_type.hpp b/boost/python/converter/to_python_function_type.hpp new file mode 100644 index 0000000000..cccd014d68 --- /dev/null +++ b/boost/python/converter/to_python_function_type.hpp @@ -0,0 +1,19 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef TO_PYTHON_FUNCTION_TYPE_DWA200236_HPP +# define TO_PYTHON_FUNCTION_TYPE_DWA200236_HPP +# include <boost/python/detail/prefix.hpp> +# include <boost/static_assert.hpp> + +namespace boost { namespace python { namespace converter { + +// The type of stored function pointers which actually do conversion +// by-value. The void* points to the object to be converted, and +// type-safety is preserved through runtime registration. +typedef PyObject* (*to_python_function_t)(void const*); + +}}} // namespace boost::python::converter + +#endif // TO_PYTHON_FUNCTION_TYPE_DWA200236_HPP diff --git a/boost/python/copy_const_reference.hpp b/boost/python/copy_const_reference.hpp new file mode 100644 index 0000000000..19e3b42332 --- /dev/null +++ b/boost/python/copy_const_reference.hpp @@ -0,0 +1,43 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef COPY_CONST_REFERENCE_DWA2002131_HPP +# define COPY_CONST_REFERENCE_DWA2002131_HPP + +# include <boost/python/detail/prefix.hpp> +# include <boost/python/detail/indirect_traits.hpp> +# include <boost/mpl/if.hpp> +# include <boost/python/to_python_value.hpp> + +namespace boost { namespace python { + +namespace detail +{ + template <class R> + struct copy_const_reference_expects_a_const_reference_return_type +# if defined(__GNUC__) && __GNUC__ >= 3 || defined(__EDG__) + {} +# endif + ; +} + +template <class T> struct to_python_value; + +struct copy_const_reference +{ + template <class T> + struct apply + { + typedef typename mpl::if_c< + indirect_traits::is_reference_to_const<T>::value + , to_python_value<T> + , detail::copy_const_reference_expects_a_const_reference_return_type<T> + >::type type; + }; +}; + + +}} // namespace boost::python + +#endif // COPY_CONST_REFERENCE_DWA2002131_HPP diff --git a/boost/python/copy_non_const_reference.hpp b/boost/python/copy_non_const_reference.hpp new file mode 100644 index 0000000000..78b70f5d3b --- /dev/null +++ b/boost/python/copy_non_const_reference.hpp @@ -0,0 +1,43 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef COPY_NON_CONST_REFERENCE_DWA2002131_HPP +# define COPY_NON_CONST_REFERENCE_DWA2002131_HPP + +# include <boost/python/detail/prefix.hpp> +# include <boost/python/detail/indirect_traits.hpp> +# include <boost/mpl/if.hpp> +# include <boost/python/to_python_value.hpp> + +namespace boost { namespace python { + +namespace detail +{ + template <class R> + struct copy_non_const_reference_expects_a_non_const_reference_return_type +# if defined(__GNUC__) && __GNUC__ >= 3 || defined(__EDG__) + {} +# endif + ; +} + +template <class T> struct to_python_value; + +struct copy_non_const_reference +{ + template <class T> + struct apply + { + typedef typename mpl::if_c< + indirect_traits::is_reference_to_non_const<T>::value + , to_python_value<T> + , detail::copy_non_const_reference_expects_a_non_const_reference_return_type<T> + >::type type; + }; +}; + + +}} // namespace boost::python + +#endif // COPY_NON_CONST_REFERENCE_DWA2002131_HPP diff --git a/boost/python/data_members.hpp b/boost/python/data_members.hpp new file mode 100644 index 0000000000..b0851fb1b3 --- /dev/null +++ b/boost/python/data_members.hpp @@ -0,0 +1,318 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef DATA_MEMBERS_DWA2002328_HPP +# define DATA_MEMBERS_DWA2002328_HPP + +# include <boost/python/detail/prefix.hpp> + +# include <boost/python/handle.hpp> + +# include <boost/python/return_value_policy.hpp> +# include <boost/python/return_by_value.hpp> +# include <boost/python/return_internal_reference.hpp> +# include <boost/python/make_function.hpp> + +# include <boost/python/converter/builtin_converters.hpp> + +# include <boost/python/detail/indirect_traits.hpp> +# include <boost/python/detail/not_specified.hpp> +# include <boost/python/detail/value_arg.hpp> + +# include <boost/type_traits/add_const.hpp> +# include <boost/type_traits/add_reference.hpp> +# include <boost/type_traits/is_member_pointer.hpp> + +# if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003)) +# include <boost/type_traits/remove_cv.hpp> +# endif + +# include <boost/mpl/eval_if.hpp> +# include <boost/mpl/if.hpp> +# include <boost/mpl/vector/vector10.hpp> + +# include <boost/detail/workaround.hpp> + +namespace boost { namespace python { + +// +// This file defines the make_getter and make_setter function +// families, which are responsible for turning pointers, references, +// and pointers-to-data-members into callable Python objects which +// can be used for attribute access on wrapped classes. +// + +namespace detail +{ + + // A small function object which handles the getting and setting of + // data members. + template <class Data, class Class> + struct member + { + public: + member(Data Class::*which) : m_which(which) {} + + Data& operator()(Class& c) const + { + return c.*m_which; + } + + void operator()(Class& c, typename value_arg<Data>::type d) const + { + c.*m_which = d; + } + private: + Data Class::*m_which; + }; + + // A small function object which handles the getting and setting of + // non-member objects. + template <class Data> + struct datum + { + public: + datum(Data *which) : m_which(which) {} + + Data& operator()() const + { + return *m_which; + } + + void operator()(typename value_arg<Data>::type d) const + { + *m_which = d; + } + private: + Data *m_which; + }; + + // + // Helper metafunction for determining the default CallPolicy to use + // for attribute access. If T is a [reference to a] class type X + // whose conversion to python would normally produce a new copy of X + // in a wrapped X class instance (as opposed to types such as + // std::string, which are converted to native Python types, and + // smart pointer types which produce a wrapped class instance of the + // pointee type), to-python conversions will attempt to produce an + // object which refers to the original C++ object, rather than a + // copy. See default_member_getter_policy for rationale. + // + template <class T> + struct default_getter_by_ref + : mpl::and_< + mpl::bool_< + to_python_value< + typename value_arg<T>::type + >::uses_registry + > + , indirect_traits::is_reference_to_class< + typename value_arg<T>::type + > + > + { + }; + + // Metafunction computing the default CallPolicy to use for reading + // data members + // + // If it's a regular class type (not an object manager or other + // type for which we have to_python specializations, use + // return_internal_reference so that we can do things like + // x.y.z = 1 + // and get the right result. + template <class T> + struct default_member_getter_policy + : mpl::if_< + default_getter_by_ref<T> + , return_internal_reference<> + , return_value_policy<return_by_value> + > + {}; + + // Metafunction computing the default CallPolicy to use for reading + // non-member data. + template <class T> + struct default_datum_getter_policy + : mpl::if_< + default_getter_by_ref<T> + , return_value_policy<reference_existing_object> + , return_value_policy<return_by_value> + > + {}; + + // + // make_getter helper function family -- These helpers to + // boost::python::make_getter are used to dispatch behavior. The + // third argument is a workaround for a CWPro8 partial ordering bug + // with pointers to data members. It should be convertible to + // mpl::true_ iff the first argument is a pointer-to-member, and + // mpl::false_ otherwise. The fourth argument is for compilers + // which don't support partial ordering at all and should always be + // passed 0L. + // + +#if BOOST_WORKAROUND(__EDG_VERSION__, <= 238) + template <class D, class P> + inline object make_getter(D& d, P& p, mpl::false_, ...); +#endif + + // Handle non-member pointers with policies + template <class D, class Policies> + inline object make_getter(D* d, Policies const& policies, mpl::false_, int) + { + return python::make_function( + detail::datum<D>(d), policies, mpl::vector1<D&>() + ); + } + + // Handle non-member pointers without policies + template <class D> + inline object make_getter(D* d, not_specified, mpl::false_, long) + { + typedef typename default_datum_getter_policy<D>::type policies; + return detail::make_getter(d, policies(), mpl::false_(), 0); + } + + // Handle pointers-to-members with policies + template <class C, class D, class Policies> + inline object make_getter(D C::*pm, Policies const& policies, mpl::true_, int) + { +#if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003)) + typedef typename remove_cv<C>::type Class; +#else + typedef C Class; +#endif + return python::make_function( + detail::member<D,Class>(pm) + , policies + , mpl::vector2<D&,Class&>() + ); + } + + // Handle pointers-to-members without policies + template <class C, class D> + inline object make_getter(D C::*pm, not_specified, mpl::true_, long) + { + typedef typename default_member_getter_policy<D>::type policies; + return detail::make_getter(pm, policies(), mpl::true_(), 0); + } + + // Handle references + template <class D, class P> + inline object make_getter(D& d, P& p, mpl::false_, ...) + { + // Just dispatch to the handler for pointer types. + return detail::make_getter(&d, p, mpl::false_(), 0L); + } + + // + // make_setter helper function family -- These helpers to + // boost::python::make_setter are used to dispatch behavior. The + // third argument is for compilers which don't support partial + // ordering at all and should always be passed 0. + // + + + // Handle non-member pointers + template <class D, class Policies> + inline object make_setter(D* p, Policies const& policies, mpl::false_, int) + { + return python::make_function( + detail::datum<D>(p), policies, mpl::vector2<void,D const&>() + ); + } + + // Handle pointers-to-members + template <class C, class D, class Policies> + inline object make_setter(D C::*pm, Policies const& policies, mpl::true_, int) + { + return python::make_function( + detail::member<D,C>(pm) + , policies + , mpl::vector3<void, C&, D const&>() + ); + } + + // Handle references + template <class D, class Policies> + inline object make_setter(D& x, Policies const& policies, mpl::false_, ...) + { + return detail::make_setter(&x, policies, mpl::false_(), 0L); + } +} + +// +// make_getter function family -- build a callable object which +// retrieves data through the first argument and is appropriate for +// use as the `get' function in Python properties . The second, +// policies argument, is optional. We need both D& and D const& +// overloads in order be able to handle rvalues. +// +template <class D, class Policies> +inline object make_getter(D& d, Policies const& policies) +{ + return detail::make_getter(d, policies, is_member_pointer<D>(), 0L); +} + +template <class D, class Policies> +inline object make_getter(D const& d, Policies const& policies) +{ + return detail::make_getter(d, policies, is_member_pointer<D>(), 0L); +} + +template <class D> +inline object make_getter(D& x) +{ + detail::not_specified policy + = detail::not_specified(); // suppress a SunPro warning + return detail::make_getter(x, policy, is_member_pointer<D>(), 0L); +} + +# if !BOOST_WORKAROUND(__EDG_VERSION__, <= 238) && !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) +template <class D> +inline object make_getter(D const& d) +{ + detail::not_specified policy + = detail::not_specified(); // Suppress a SunPro warning + return detail::make_getter(d, policy, is_member_pointer<D>(), 0L); +} +# endif + +// +// make_setter function family -- build a callable object which +// writes data through the first argument and is appropriate for +// use as the `set' function in Python properties . The second, +// policies argument, is optional. We need both D& and D const& +// overloads in order be able to handle rvalues. +// +template <class D, class Policies> +inline object make_setter(D& x, Policies const& policies) +{ + return detail::make_setter(x, policies, is_member_pointer<D>(), 0); +} + +template <class D, class Policies> +inline object make_setter(D const& x, Policies const& policies) +{ + return detail::make_setter(x, policies, is_member_pointer<D>(), 0); +} + +template <class D> +inline object make_setter(D& x) +{ + return detail::make_setter(x, default_call_policies(), is_member_pointer<D>(), 0); +} + +# if !(BOOST_WORKAROUND(BOOST_MSVC, <= 1300) || BOOST_WORKAROUND(__EDG_VERSION__, <= 238)) +template <class D> +inline object make_setter(D const& x) +{ + return detail::make_setter(x, default_call_policies(), is_member_pointer<D>(), 0); +} +# endif + +}} // namespace boost::python + +#endif // DATA_MEMBERS_DWA2002328_HPP diff --git a/boost/python/def.hpp b/boost/python/def.hpp new file mode 100644 index 0000000000..76829b0855 --- /dev/null +++ b/boost/python/def.hpp @@ -0,0 +1,114 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef DEF_DWA200292_HPP +# define DEF_DWA200292_HPP + +# include <boost/python/detail/prefix.hpp> + +# include <boost/python/object_fwd.hpp> +# include <boost/python/make_function.hpp> +# include <boost/python/detail/def_helper.hpp> +# include <boost/python/detail/overloads_fwd.hpp> +# include <boost/python/scope.hpp> +# include <boost/python/signature.hpp> +# include <boost/python/detail/scope.hpp> + +namespace boost { namespace python { + +namespace detail +{ + namespace error + { + // Compile-time error messages + template <bool> struct multiple_functions_passed_to_def; + template <> struct multiple_functions_passed_to_def<false> { typedef char type; }; + } + + // + // def_from_helper -- + // + // Use a def_helper to define a regular wrapped function in the current scope. + template <class F, class Helper> + void def_from_helper( + char const* name, F const& fn, Helper const& helper) + { + // Must not try to use default implementations except with method definitions. + typedef typename error::multiple_functions_passed_to_def< + Helper::has_default_implementation + >::type assertion; + + detail::scope_setattr_doc( + name, boost::python::make_function( + fn + , helper.policies() + , helper.keywords()) + , helper.doc() + ); + } + + // + // These two overloads discriminate between def() as applied to + // regular functions and def() as applied to the result of + // BOOST_PYTHON_FUNCTION_OVERLOADS(). The final argument is used to + // discriminate. + // + template <class Fn, class A1> + void + def_maybe_overloads( + char const* name + , Fn fn + , A1 const& a1 + , ...) + { + detail::def_from_helper(name, fn, def_helper<A1>(a1)); + } + + template <class StubsT, class SigT> + void def_maybe_overloads( + char const* name + , SigT sig + , StubsT const& stubs + , detail::overloads_base const*) + { + scope current; + + detail::define_with_defaults( + name, stubs, current, detail::get_signature(sig)); + } + + template <class T> + object make_function1(T fn, ...) { return make_function(fn); } + + inline + object make_function1(object const& x, object const*) { return x; } +} + +template <class Fn> +void def(char const* name, Fn fn) +{ + detail::scope_setattr_doc(name, detail::make_function1(fn, &fn), 0); +} + +template <class Arg1T, class Arg2T> +void def(char const* name, Arg1T arg1, Arg2T const& arg2) +{ + detail::def_maybe_overloads(name, arg1, arg2, &arg2); +} + +template <class F, class A1, class A2> +void def(char const* name, F f, A1 const& a1, A2 const& a2) +{ + detail::def_from_helper(name, f, detail::def_helper<A1,A2>(a1,a2)); +} + +template <class F, class A1, class A2, class A3> +void def(char const* name, F f, A1 const& a1, A2 const& a2, A3 const& a3) +{ + detail::def_from_helper(name, f, detail::def_helper<A1,A2,A3>(a1,a2,a3)); +} + +}} // namespace boost::python + +#endif // DEF_DWA200292_HPP diff --git a/boost/python/def_visitor.hpp b/boost/python/def_visitor.hpp new file mode 100644 index 0000000000..9c8907cd6f --- /dev/null +++ b/boost/python/def_visitor.hpp @@ -0,0 +1,86 @@ +// Copyright David Abrahams 2003. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef DEF_VISITOR_DWA2003810_HPP +# define DEF_VISITOR_DWA2003810_HPP + +# include <boost/python/detail/prefix.hpp> +# include <boost/detail/workaround.hpp> + +namespace boost { namespace python { + +template <class DerivedVisitor> class def_visitor; +template <class T, class X1, class X2, class X3> class class_; + +class def_visitor_access +{ +# if defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) \ + || BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551)) + // Tasteless as this may seem, making all members public allows member templates + // to work in the absence of member template friends. + public: +# else + template <class Derived> friend class def_visitor; +# endif + + // unnamed visit, c.f. init<...>, container suites + template <class V, class classT> + static void visit(V const& v, classT& c) + { + v.derived_visitor().visit(c); + } + + // named visit, c.f. object, pure_virtual + template <class V, class classT, class OptionalArgs> + static void visit( + V const& v + , classT& c + , char const* name + , OptionalArgs const& options + ) + { + v.derived_visitor().visit(c, name, options); + } + +}; + + +template <class DerivedVisitor> +class def_visitor +{ + friend class def_visitor_access; + +# if defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) \ + || BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551)) + // Tasteless as this may seem, making all members public allows member templates + // to work in the absence of member template friends. + public: +# else + template <class T, class X1, class X2, class X3> friend class class_; +# endif + + // unnamed visit, c.f. init<...>, container suites + template <class classT> + void visit(classT& c) const + { + def_visitor_access::visit(*this, c); + } + + // named visit, c.f. object, pure_virtual + template <class classT, class OptionalArgs> + void visit(classT& c, char const* name, OptionalArgs const& options) const + { + def_visitor_access::visit(*this, c, name, options); + } + + protected: + DerivedVisitor const& derived_visitor() const + { + return static_cast<DerivedVisitor const&>(*this); + } +}; + +}} // namespace boost::python + +#endif // DEF_VISITOR_DWA2003810_HPP diff --git a/boost/python/default_call_policies.hpp b/boost/python/default_call_policies.hpp new file mode 100644 index 0000000000..3d32d2eb49 --- /dev/null +++ b/boost/python/default_call_policies.hpp @@ -0,0 +1,91 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef DEFAULT_CALL_POLICIES_DWA2002131_HPP +# define DEFAULT_CALL_POLICIES_DWA2002131_HPP + +# include <boost/python/detail/prefix.hpp> +# include <boost/mpl/if.hpp> +# include <boost/python/to_python_value.hpp> +# include <boost/python/detail/value_arg.hpp> +# include <boost/type_traits/transform_traits.hpp> +# include <boost/type_traits/is_pointer.hpp> +# include <boost/type_traits/is_reference.hpp> +# include <boost/mpl/or.hpp> +# include <boost/mpl/front.hpp> + +namespace boost { namespace python { + +template <class T> struct to_python_value; + +namespace detail +{ +// for "readable" error messages + template <class T> struct specify_a_return_value_policy_to_wrap_functions_returning +# if defined(__GNUC__) && __GNUC__ >= 3 || defined(__EDG__) + {} +# endif + ; +} + +struct default_result_converter; + +struct default_call_policies +{ + // Ownership of this argument tuple will ultimately be adopted by + // the caller. + template <class ArgumentPackage> + static bool precall(ArgumentPackage const&) + { + return true; + } + + // Pass the result through + template <class ArgumentPackage> + static PyObject* postcall(ArgumentPackage const&, PyObject* result) + { + return result; + } + + typedef default_result_converter result_converter; + typedef PyObject* argument_package; + + template <class Sig> + struct extract_return_type : mpl::front<Sig> + { + }; + +}; + +struct default_result_converter +{ + template <class R> + struct apply + { + typedef typename mpl::if_< + mpl::or_<is_pointer<R>, is_reference<R> > + , detail::specify_a_return_value_policy_to_wrap_functions_returning<R> + , boost::python::to_python_value< + typename detail::value_arg<R>::type + > + >::type type; + }; +}; + +// Exceptions for c strings an PyObject*s +template <> +struct default_result_converter::apply<char const*> +{ + typedef boost::python::to_python_value<char const*const&> type; +}; + +template <> +struct default_result_converter::apply<PyObject*> +{ + typedef boost::python::to_python_value<PyObject*const&> type; +}; + +}} // namespace boost::python + +#endif // DEFAULT_CALL_POLICIES_DWA2002131_HPP diff --git a/boost/python/detail/aix_init_module.hpp b/boost/python/detail/aix_init_module.hpp new file mode 100644 index 0000000000..9214dbf09b --- /dev/null +++ b/boost/python/detail/aix_init_module.hpp @@ -0,0 +1,26 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef AIX_INIT_MODULE_DWA2002529_HPP +# define AIX_INIT_MODULE_DWA2002529_HPP +# ifdef _AIX +# include <boost/python/detail/prefix.hpp> +# include <cstdio> +# ifdef __KCC +# include <iostream> // this works around a problem in KCC 4.0f +# endif + +namespace boost { namespace python { namespace detail { + +extern "C" +{ + typedef PyObject* (*so_load_function)(char*,char*,FILE*); +} + +void aix_init_module(so_load_function, char const* name, void (*init_module)()); + +}}} // namespace boost::python::detail +# endif + +#endif // AIX_INIT_MODULE_DWA2002529_HPP diff --git a/boost/python/detail/api_placeholder.hpp b/boost/python/detail/api_placeholder.hpp new file mode 100644 index 0000000000..5975a13bda --- /dev/null +++ b/boost/python/detail/api_placeholder.hpp @@ -0,0 +1,15 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// DEPRECATED HEADER (2006 Jan 12) +// Provided only for backward compatibility. +// The boost::python::len() function is now defined in object.hpp. + +#ifndef BOOST_PYTHON_API_PLACE_HOLDER_HPP +#define BOOST_PYTHON_API_PLACE_HOLDER_HPP + +#include <boost/python/object.hpp> + +#endif // BOOST_PYTHON_API_PLACE_HOLDER_HPP diff --git a/boost/python/detail/borrowed_ptr.hpp b/boost/python/detail/borrowed_ptr.hpp new file mode 100644 index 0000000000..b88457b83a --- /dev/null +++ b/boost/python/detail/borrowed_ptr.hpp @@ -0,0 +1,111 @@ +#ifndef BORROWED_PTR_DWA20020601_HPP +# define BORROWED_PTR_DWA20020601_HPP +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +# include <boost/config.hpp> +# include <boost/type.hpp> +# include <boost/mpl/if.hpp> +# include <boost/type_traits/object_traits.hpp> +# include <boost/type_traits/cv_traits.hpp> +# include <boost/python/tag.hpp> + +namespace boost { namespace python { namespace detail { + +template<class T> class borrowed +{ + typedef T type; +}; + +# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +template<typename T> +struct is_borrowed_ptr +{ + BOOST_STATIC_CONSTANT(bool, value = false); +}; + +# if !defined(__MWERKS__) || __MWERKS__ > 0x3000 +template<typename T> +struct is_borrowed_ptr<borrowed<T>*> +{ + BOOST_STATIC_CONSTANT(bool, value = true); +}; + +template<typename T> +struct is_borrowed_ptr<borrowed<T> const*> +{ + BOOST_STATIC_CONSTANT(bool, value = true); +}; + +template<typename T> +struct is_borrowed_ptr<borrowed<T> volatile*> +{ + BOOST_STATIC_CONSTANT(bool, value = true); +}; + +template<typename T> +struct is_borrowed_ptr<borrowed<T> const volatile*> +{ + BOOST_STATIC_CONSTANT(bool, value = true); +}; +# else +template<typename T> +struct is_borrowed +{ + BOOST_STATIC_CONSTANT(bool, value = false); +}; +template<typename T> +struct is_borrowed<borrowed<T> > +{ + BOOST_STATIC_CONSTANT(bool, value = true); +}; +template<typename T> +struct is_borrowed_ptr<T*> + : is_borrowed<typename remove_cv<T>::type> +{ +}; +# endif + +# else // no partial specialization + +typedef char (&yes_borrowed_ptr_t)[1]; +typedef char (&no_borrowed_ptr_t)[2]; + +no_borrowed_ptr_t is_borrowed_ptr_test(...); + +template <class T> +typename mpl::if_c< + is_pointer<T>::value + , T + , int + >::type +is_borrowed_ptr_test1(boost::type<T>); + +template<typename T> +yes_borrowed_ptr_t is_borrowed_ptr_test(borrowed<T> const volatile*); + +template<typename T> +class is_borrowed_ptr +{ + public: + BOOST_STATIC_CONSTANT( + bool, value = ( + sizeof(detail::is_borrowed_ptr_test(is_borrowed_ptr_test1(boost::type<T>()))) + == sizeof(detail::yes_borrowed_ptr_t))); +}; + +# endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + +} + +template <class T> +inline T* get_managed_object(detail::borrowed<T> const volatile* p, tag_t) +{ + return (T*)p; +} + +}} // namespace boost::python::detail + +#endif // #ifndef BORROWED_PTR_DWA20020601_HPP diff --git a/boost/python/detail/caller.hpp b/boost/python/detail/caller.hpp new file mode 100644 index 0000000000..e479bf427d --- /dev/null +++ b/boost/python/detail/caller.hpp @@ -0,0 +1,259 @@ +#if !defined(BOOST_PP_IS_ITERATING) + +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +# ifndef CALLER_DWA20021121_HPP +# define CALLER_DWA20021121_HPP + +# include <boost/python/type_id.hpp> +# include <boost/python/handle.hpp> + +# include <boost/detail/indirect_traits.hpp> + +# include <boost/python/detail/invoke.hpp> +# include <boost/python/detail/signature.hpp> +# include <boost/python/detail/preprocessor.hpp> + +# include <boost/python/arg_from_python.hpp> +# include <boost/python/converter/context_result_converter.hpp> +# include <boost/python/converter/builtin_converters.hpp> + +# include <boost/preprocessor/iterate.hpp> +# include <boost/preprocessor/cat.hpp> +# include <boost/preprocessor/dec.hpp> +# include <boost/preprocessor/if.hpp> +# include <boost/preprocessor/iteration/local.hpp> +# include <boost/preprocessor/repetition/enum_trailing_params.hpp> +# include <boost/preprocessor/repetition/repeat.hpp> + +# include <boost/compressed_pair.hpp> + +# include <boost/type_traits/is_same.hpp> +# include <boost/type_traits/is_convertible.hpp> + +# include <boost/mpl/apply.hpp> +# include <boost/mpl/eval_if.hpp> +# include <boost/mpl/identity.hpp> +# include <boost/mpl/size.hpp> +# include <boost/mpl/at.hpp> +# include <boost/mpl/int.hpp> +# include <boost/mpl/next.hpp> + +namespace boost { namespace python { namespace detail { + +template <int N> +inline PyObject* get(mpl::int_<N>, PyObject* const& args_) +{ + return PyTuple_GET_ITEM(args_,N); +} + +inline unsigned arity(PyObject* const& args_) +{ + return PyTuple_GET_SIZE(args_); +} + +// This "result converter" is really just used as +// a dispatch tag to invoke(...), selecting the appropriate +// implementation +typedef int void_result_to_python; + +// Given a model of CallPolicies and a C++ result type, this +// metafunction selects the appropriate converter to use for +// converting the result to python. +template <class Policies, class Result> +struct select_result_converter + : mpl::eval_if< + is_same<Result,void> + , mpl::identity<void_result_to_python> + , mpl::apply1<typename Policies::result_converter,Result> + > +{ +}; + +template <class ArgPackage, class ResultConverter> +inline ResultConverter create_result_converter( + ArgPackage const& args_ + , ResultConverter* + , converter::context_result_converter* +) +{ + return ResultConverter(args_); +} + +template <class ArgPackage, class ResultConverter> +inline ResultConverter create_result_converter( + ArgPackage const& + , ResultConverter* + , ... +) +{ + return ResultConverter(); +} + +#ifndef BOOST_PYTHON_NO_PY_SIGNATURES +template <class ResultConverter> +struct converter_target_type +{ + static PyTypeObject const *get_pytype() + { + return create_result_converter((PyObject*)0, (ResultConverter *)0, (ResultConverter *)0).get_pytype(); + } +}; + +template < > +struct converter_target_type <void_result_to_python > +{ + static PyTypeObject const *get_pytype() + { + return 0; + } +}; +#endif + + +template <unsigned> struct caller_arity; + +template <class F, class CallPolicies, class Sig> +struct caller; + +# define BOOST_PYTHON_NEXT(init,name,n) \ + typedef BOOST_PP_IF(n,typename mpl::next< BOOST_PP_CAT(name,BOOST_PP_DEC(n)) >::type, init) name##n; + +# define BOOST_PYTHON_ARG_CONVERTER(n) \ + BOOST_PYTHON_NEXT(typename mpl::next<first>::type, arg_iter,n) \ + typedef arg_from_python<BOOST_DEDUCED_TYPENAME arg_iter##n::type> c_t##n; \ + c_t##n c##n(get(mpl::int_<n>(), inner_args)); \ + if (!c##n.convertible()) \ + return 0; + +# define BOOST_PP_ITERATION_PARAMS_1 \ + (3, (0, BOOST_PYTHON_MAX_ARITY + 1, <boost/python/detail/caller.hpp>)) +# include BOOST_PP_ITERATE() + +# undef BOOST_PYTHON_ARG_CONVERTER +# undef BOOST_PYTHON_NEXT + +// A metafunction returning the base class used for caller<class F, +// class ConverterGenerators, class CallPolicies, class Sig>. +template <class F, class CallPolicies, class Sig> +struct caller_base_select +{ + enum { arity = mpl::size<Sig>::value - 1 }; + typedef typename caller_arity<arity>::template impl<F,CallPolicies,Sig> type; +}; + +// A function object type which wraps C++ objects as Python callable +// objects. +// +// Template Arguments: +// +// F - +// the C++ `function object' that will be called. Might +// actually be any data for which an appropriate invoke_tag() can +// be generated. invoke(...) takes care of the actual invocation syntax. +// +// CallPolicies - +// The precall, postcall, and what kind of resultconverter to +// generate for mpl::front<Sig>::type +// +// Sig - +// The `intended signature' of the function. An MPL sequence +// beginning with a result type and continuing with a list of +// argument types. +template <class F, class CallPolicies, class Sig> +struct caller + : caller_base_select<F,CallPolicies,Sig>::type +{ + typedef typename caller_base_select< + F,CallPolicies,Sig + >::type base; + + typedef PyObject* result_type; + + caller(F f, CallPolicies p) : base(f,p) {} + +}; + +}}} // namespace boost::python::detail + +# endif // CALLER_DWA20021121_HPP + +#else + +# define N BOOST_PP_ITERATION() + +template <> +struct caller_arity<N> +{ + template <class F, class Policies, class Sig> + struct impl + { + impl(F f, Policies p) : m_data(f,p) {} + + PyObject* operator()(PyObject* args_, PyObject*) // eliminate + // this + // trailing + // keyword dict + { + typedef typename mpl::begin<Sig>::type first; + typedef typename first::type result_t; + typedef typename select_result_converter<Policies, result_t>::type result_converter; + typedef typename Policies::argument_package argument_package; + + argument_package inner_args(args_); + +# if N +# define BOOST_PP_LOCAL_MACRO(i) BOOST_PYTHON_ARG_CONVERTER(i) +# define BOOST_PP_LOCAL_LIMITS (0, N-1) +# include BOOST_PP_LOCAL_ITERATE() +# endif + // all converters have been checked. Now we can do the + // precall part of the policy + if (!m_data.second().precall(inner_args)) + return 0; + + PyObject* result = detail::invoke( + detail::invoke_tag<result_t,F>() + , create_result_converter(args_, (result_converter*)0, (result_converter*)0) + , m_data.first() + BOOST_PP_ENUM_TRAILING_PARAMS(N, c) + ); + + return m_data.second().postcall(inner_args, result); + } + + static unsigned min_arity() { return N; } + + static py_func_sig_info signature() + { + const signature_element * sig = detail::signature<Sig>::elements(); +#ifndef BOOST_PYTHON_NO_PY_SIGNATURES + + typedef BOOST_DEDUCED_TYPENAME Policies::template extract_return_type<Sig>::type rtype; + typedef typename select_result_converter<Policies, rtype>::type result_converter; + + static const signature_element ret = { + (boost::is_void<rtype>::value ? "void" : type_id<rtype>().name()) + , &detail::converter_target_type<result_converter>::get_pytype + , boost::detail::indirect_traits::is_reference_to_non_const<rtype>::value + }; + py_func_sig_info res = {sig, &ret }; +#else + py_func_sig_info res = {sig, sig }; +#endif + + return res; + } + private: + compressed_pair<F,Policies> m_data; + }; +}; + + + +#endif // BOOST_PP_IS_ITERATING + + diff --git a/boost/python/detail/config.hpp b/boost/python/detail/config.hpp new file mode 100644 index 0000000000..acafc03747 --- /dev/null +++ b/boost/python/detail/config.hpp @@ -0,0 +1,141 @@ +// (C) Copyright David Abrahams 2000. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// The author gratefully acknowleges the support of Dragon Systems, Inc., in +// producing this work. + +// Revision History: +// 04 Mar 01 Some fixes so it will compile with Intel C++ (Dave Abrahams) + +#ifndef CONFIG_DWA052200_H_ +# define CONFIG_DWA052200_H_ + +# include <boost/config.hpp> +# include <boost/detail/workaround.hpp> + +# ifdef BOOST_NO_OPERATORS_IN_NAMESPACE + // A gcc bug forces some symbols into the global namespace +# define BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE +# define BOOST_PYTHON_END_CONVERSION_NAMESPACE +# define BOOST_PYTHON_CONVERSION +# define BOOST_PYTHON_IMPORT_CONVERSION(x) using ::x +# else +# define BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE namespace boost { namespace python { +# define BOOST_PYTHON_END_CONVERSION_NAMESPACE }} // namespace boost::python +# define BOOST_PYTHON_CONVERSION boost::python +# define BOOST_PYTHON_IMPORT_CONVERSION(x) void never_defined() // so we can follow the macro with a ';' +# endif + +# if defined(BOOST_MSVC) +# if _MSC_VER < 1300 +# define BOOST_MSVC6_OR_EARLIER 1 +# endif + +# pragma warning (disable : 4786) // disable truncated debug symbols +# pragma warning (disable : 4251) // disable exported dll function +# pragma warning (disable : 4800) //'int' : forcing value to bool 'true' or 'false' +# pragma warning (disable : 4275) // non dll-interface class + +# elif defined(__ICL) && __ICL < 600 // Intel C++ 5 + +# pragma warning(disable: 985) // identifier was truncated in debug information + +# endif + +// The STLport puts all of the standard 'C' library names in std (as far as the +// user is concerned), but without it you need a fix if you're using MSVC or +// Intel C++ +# if defined(BOOST_NO_STDC_NAMESPACE) +# define BOOST_CSTD_ +# else +# define BOOST_CSTD_ std +# endif + +/***************************************************************************** + * + * Set up dll import/export options: + * + ****************************************************************************/ + +// backwards compatibility: +#ifdef BOOST_PYTHON_STATIC_LIB +# define BOOST_PYTHON_STATIC_LINK +# elif !defined(BOOST_PYTHON_DYNAMIC_LIB) +# define BOOST_PYTHON_DYNAMIC_LIB +#endif + +#if defined(BOOST_PYTHON_DYNAMIC_LIB) + +# if !defined(_WIN32) && !defined(__CYGWIN__) \ + && !defined(BOOST_PYTHON_USE_GCC_SYMBOL_VISIBILITY) \ + && BOOST_WORKAROUND(__GNUC__, >= 3) && (__GNUC_MINOR__ >=5 || __GNUC__ > 3) +# define BOOST_PYTHON_USE_GCC_SYMBOL_VISIBILITY 1 +# endif + +# if BOOST_PYTHON_USE_GCC_SYMBOL_VISIBILITY +# if defined(BOOST_PYTHON_SOURCE) +# define BOOST_PYTHON_DECL __attribute__ ((visibility("default"))) +# define BOOST_PYTHON_BUILD_DLL +# else +# define BOOST_PYTHON_DECL +# endif +# define BOOST_PYTHON_DECL_FORWARD +# define BOOST_PYTHON_DECL_EXCEPTION __attribute__ ((visibility("default"))) +# elif (defined(_WIN32) || defined(__CYGWIN__)) +# if defined(BOOST_PYTHON_SOURCE) +# define BOOST_PYTHON_DECL __declspec(dllexport) +# define BOOST_PYTHON_BUILD_DLL +# else +# define BOOST_PYTHON_DECL __declspec(dllimport) +# endif +# endif + +#endif + +#ifndef BOOST_PYTHON_DECL +# define BOOST_PYTHON_DECL +#endif + +#ifndef BOOST_PYTHON_DECL_FORWARD +# define BOOST_PYTHON_DECL_FORWARD BOOST_PYTHON_DECL +#endif + +#ifndef BOOST_PYTHON_DECL_EXCEPTION +# define BOOST_PYTHON_DECL_EXCEPTION BOOST_PYTHON_DECL +#endif + +#if BOOST_WORKAROUND(__DECCXX_VER, BOOST_TESTED_AT(60590042)) +// Replace broken Tru64/cxx offsetof macro +# define BOOST_PYTHON_OFFSETOF(s_name, s_member) \ + ((size_t)__INTADDR__(&(((s_name *)0)->s_member))) +#else +# define BOOST_PYTHON_OFFSETOF offsetof +#endif + +// enable automatic library variant selection ------------------------------// + +#if !defined(BOOST_PYTHON_SOURCE) && !defined(BOOST_ALL_NO_LIB) && !defined(BOOST_PYTHON_NO_LIB) +// +// Set the name of our library, this will get undef'ed by auto_link.hpp +// once it's done with it: +// +#define BOOST_LIB_NAME boost_python +// +// If we're importing code from a dll, then tell auto_link.hpp about it: +// +#ifdef BOOST_PYTHON_DYNAMIC_LIB +# define BOOST_DYN_LINK +#endif +// +// And include the header that does the work: +// +#include <boost/config/auto_link.hpp> +#endif // auto-linking disabled + +#ifndef BOOST_PYTHON_NO_PY_SIGNATURES +#define BOOST_PYTHON_SUPPORTS_PY_SIGNATURES // enables smooth transition +#endif + +#endif // CONFIG_DWA052200_H_ diff --git a/boost/python/detail/construct.hpp b/boost/python/detail/construct.hpp new file mode 100644 index 0000000000..5f15d22c6e --- /dev/null +++ b/boost/python/detail/construct.hpp @@ -0,0 +1,42 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef CONSTRUCT_REFERENCE_DWA2002716_HPP +# define CONSTRUCT_REFERENCE_DWA2002716_HPP + +namespace boost { namespace python { namespace detail { + +template <class T, class Arg> +void construct_pointee(void* storage, Arg& x +# if !defined(BOOST_MSVC) || BOOST_MSVC > 1300 + , T const volatile* +# else + , T const* +# endif + ) +{ + new (storage) T(x); +} + +template <class T, class Arg> +void construct_referent_impl(void* storage, Arg& x, T&(*)()) +{ + construct_pointee(storage, x, (T*)0); +} + +template <class T, class Arg> +void construct_referent(void* storage, Arg const& x, T(*tag)() = 0) +{ + construct_referent_impl(storage, x, tag); +} + +template <class T, class Arg> +void construct_referent(void* storage, Arg& x, T(*tag)() = 0) +{ + construct_referent_impl(storage, x, tag); +} + +}}} // namespace boost::python::detail + +#endif // CONSTRUCT_REFERENCE_DWA2002716_HPP diff --git a/boost/python/detail/convertible.hpp b/boost/python/detail/convertible.hpp new file mode 100644 index 0000000000..2ce552f5f7 --- /dev/null +++ b/boost/python/detail/convertible.hpp @@ -0,0 +1,38 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef CONVERTIBLE_DWA2002614_HPP +# define CONVERTIBLE_DWA2002614_HPP + +# if defined(__EDG_VERSION__) && __EDG_VERSION__ <= 241 +# include <boost/mpl/if.hpp> +# include <boost/type_traits/conversion_traits.hpp> +# endif + +// Supplies a runtime is_convertible check which can be used with tag +// dispatching to work around the Metrowerks Pro7 limitation with boost::is_convertible +namespace boost { namespace python { namespace detail { + +typedef char* yes_convertible; +typedef int* no_convertible; + +template <class Target> +struct convertible +{ +# if !defined(__EDG_VERSION__) || __EDG_VERSION__ > 241 || __EDG_VERSION__ == 238 + static inline no_convertible check(...) { return 0; } + static inline yes_convertible check(Target) { return 0; } +# else + template <class X> + static inline typename mpl::if_c< + is_convertible<X,Target>::value + , yes_convertible + , no_convertible + >::type check(X const&) { return 0; } +# endif +}; + +}}} // namespace boost::python::detail + +#endif // CONVERTIBLE_DWA2002614_HPP diff --git a/boost/python/detail/copy_ctor_mutates_rhs.hpp b/boost/python/detail/copy_ctor_mutates_rhs.hpp new file mode 100644 index 0000000000..4ca8d03911 --- /dev/null +++ b/boost/python/detail/copy_ctor_mutates_rhs.hpp @@ -0,0 +1,21 @@ +// Copyright David Abrahams 2003. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef COPY_CTOR_MUTATES_RHS_DWA2003219_HPP +# define COPY_CTOR_MUTATES_RHS_DWA2003219_HPP + +#include <boost/python/detail/is_auto_ptr.hpp> +#include <boost/mpl/bool.hpp> + +namespace boost { namespace python { namespace detail { + +template <class T> +struct copy_ctor_mutates_rhs + : is_auto_ptr<T> +{ +}; + +}}} // namespace boost::python::detail + +#endif // COPY_CTOR_MUTATES_RHS_DWA2003219_HPP diff --git a/boost/python/detail/cv_category.hpp b/boost/python/detail/cv_category.hpp new file mode 100644 index 0000000000..1765b36f8c --- /dev/null +++ b/boost/python/detail/cv_category.hpp @@ -0,0 +1,36 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef CV_CATEGORY_DWA200222_HPP +# define CV_CATEGORY_DWA200222_HPP +# include <boost/type_traits/cv_traits.hpp> + +namespace boost { namespace python { namespace detail { + +template <bool is_const_, bool is_volatile_> +struct cv_tag +{ + BOOST_STATIC_CONSTANT(bool, is_const = is_const_); + BOOST_STATIC_CONSTANT(bool, is_volatile = is_const_); +}; + +typedef cv_tag<false,false> cv_unqualified; +typedef cv_tag<true,false> const_; +typedef cv_tag<false,true> volatile_; +typedef cv_tag<true,true> const_volatile_; + +template <class T> +struct cv_category +{ +// BOOST_STATIC_CONSTANT(bool, c = is_const<T>::value); +// BOOST_STATIC_CONSTANT(bool, v = is_volatile<T>::value); + typedef cv_tag< + ::boost::is_const<T>::value + , ::boost::is_volatile<T>::value + > type; +}; + +}}} // namespace boost::python::detail + +#endif // CV_CATEGORY_DWA200222_HPP diff --git a/boost/python/detail/dealloc.hpp b/boost/python/detail/dealloc.hpp new file mode 100644 index 0000000000..f2d914b18c --- /dev/null +++ b/boost/python/detail/dealloc.hpp @@ -0,0 +1,17 @@ +// Copyright Gottfried Ganßauge 2003. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +# ifndef BOOST_PYTHON_DETAIL_DEALLOC_HPP_ +# define BOOST_PYTHON_DETAIL_DEALLOC_HPP_ +namespace boost { namespace python { namespace detail { + extern "C" + { + inline void dealloc(PyObject* self) + { + PyObject_Del(self); + } + } +}}} // namespace boost::python::detail +# endif // BOOST_PYTHON_DETAIL_DEALLOC_HPP_ diff --git a/boost/python/detail/decorated_type_id.hpp b/boost/python/detail/decorated_type_id.hpp new file mode 100644 index 0000000000..535508b43d --- /dev/null +++ b/boost/python/detail/decorated_type_id.hpp @@ -0,0 +1,76 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef DECORATED_TYPE_ID_DWA2002517_HPP +# define DECORATED_TYPE_ID_DWA2002517_HPP + +# include <boost/python/type_id.hpp> +# include <boost/python/detail/indirect_traits.hpp> +# include <boost/type_traits/cv_traits.hpp> + +namespace boost { namespace python { namespace detail { + +struct decorated_type_info : totally_ordered<decorated_type_info> +{ + enum decoration { const_ = 0x1, volatile_ = 0x2, reference = 0x4 }; + + decorated_type_info(type_info, decoration = decoration()); + + inline bool operator<(decorated_type_info const& rhs) const; + inline bool operator==(decorated_type_info const& rhs) const; + + friend BOOST_PYTHON_DECL std::ostream& operator<<(std::ostream&, decorated_type_info const&); + + operator type_info const&() const; + private: // type + typedef type_info base_id_t; + + private: // data members + decoration m_decoration; + base_id_t m_base_type; +}; + +template <class T> +inline decorated_type_info decorated_type_id(boost::type<T>* = 0) +{ + return decorated_type_info( + type_id<T>() + , decorated_type_info::decoration( + (is_const<T>::value || indirect_traits::is_reference_to_const<T>::value + ? decorated_type_info::const_ : 0) + | (is_volatile<T>::value || indirect_traits::is_reference_to_volatile<T>::value + ? decorated_type_info::volatile_ : 0) + | (is_reference<T>::value ? decorated_type_info::reference : 0) + ) + ); +} + +inline decorated_type_info::decorated_type_info(type_info base_t, decoration decoration) + : m_decoration(decoration) + , m_base_type(base_t) +{ +} + +inline bool decorated_type_info::operator<(decorated_type_info const& rhs) const +{ + return m_decoration < rhs.m_decoration + || (m_decoration == rhs.m_decoration + && m_base_type < rhs.m_base_type); +} + +inline bool decorated_type_info::operator==(decorated_type_info const& rhs) const +{ + return m_decoration == rhs.m_decoration && m_base_type == rhs.m_base_type; +} + +inline decorated_type_info::operator type_info const&() const +{ + return m_base_type; +} + +BOOST_PYTHON_DECL std::ostream& operator<<(std::ostream&, decorated_type_info const&); + +}}} // namespace boost::python::detail + +#endif // DECORATED_TYPE_ID_DWA2002517_HPP diff --git a/boost/python/detail/decref_guard.hpp b/boost/python/detail/decref_guard.hpp new file mode 100644 index 0000000000..d713e0a604 --- /dev/null +++ b/boost/python/detail/decref_guard.hpp @@ -0,0 +1,21 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef DECREF_GUARD_DWA20021220_HPP +# define DECREF_GUARD_DWA20021220_HPP + +namespace boost { namespace python { namespace detail { + +struct decref_guard +{ + decref_guard(PyObject* o) : obj(o) {} + ~decref_guard() { Py_XDECREF(obj); } + void cancel() { obj = 0; } + private: + PyObject* obj; +}; + +}}} // namespace boost::python::detail + +#endif // DECREF_GUARD_DWA20021220_HPP diff --git a/boost/python/detail/def_helper.hpp b/boost/python/detail/def_helper.hpp new file mode 100644 index 0000000000..e68ca0cd7b --- /dev/null +++ b/boost/python/detail/def_helper.hpp @@ -0,0 +1,212 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef DEF_HELPER_DWA200287_HPP +# define DEF_HELPER_DWA200287_HPP + +# include <boost/python/args.hpp> +# include <boost/type_traits/ice.hpp> +# include <boost/type_traits/same_traits.hpp> +# include <boost/python/detail/indirect_traits.hpp> +# include <boost/mpl/not.hpp> +# include <boost/mpl/and.hpp> +# include <boost/mpl/or.hpp> +# include <boost/type_traits/add_reference.hpp> +# include <boost/mpl/lambda.hpp> +# include <boost/mpl/apply.hpp> +# include <boost/tuple/tuple.hpp> +# include <boost/python/detail/not_specified.hpp> +# include <boost/python/detail/def_helper_fwd.hpp> + +namespace boost { namespace python { + +struct default_call_policies; + +namespace detail +{ + // tuple_extract<Tuple,Predicate>::extract(t) returns the first + // element of a Tuple whose type E satisfies the given Predicate + // applied to add_reference<E>. The Predicate must be an MPL + // metafunction class. + template <class Tuple, class Predicate> + struct tuple_extract; + + // Implementation class for when the tuple's head type does not + // satisfy the Predicate + template <bool matched> + struct tuple_extract_impl + { + template <class Tuple, class Predicate> + struct apply + { + typedef typename Tuple::head_type result_type; + + static typename Tuple::head_type extract(Tuple const& x) + { + return x.get_head(); + } + }; + }; + + // Implementation specialization for when the tuple's head type + // satisfies the predicate + template <> + struct tuple_extract_impl<false> + { + template <class Tuple, class Predicate> + struct apply + { + // recursive application of tuple_extract on the tail of the tuple + typedef tuple_extract<typename Tuple::tail_type, Predicate> next; + typedef typename next::result_type result_type; + + static result_type extract(Tuple const& x) + { + return next::extract(x.get_tail()); + } + }; + }; + + // A metafunction which selects a version of tuple_extract_impl to + // use for the implementation of tuple_extract + template <class Tuple, class Predicate> + struct tuple_extract_base_select + { + typedef typename Tuple::head_type head_type; + typedef typename mpl::apply1<Predicate, typename add_reference<head_type>::type>::type match_t; + BOOST_STATIC_CONSTANT(bool, match = match_t::value); + typedef typename tuple_extract_impl<match>::template apply<Tuple,Predicate> type; + }; + + template <class Tuple, class Predicate> + struct tuple_extract + : tuple_extract_base_select< + Tuple + , typename mpl::lambda<Predicate>::type + >::type + { + }; + + + // + // Specialized extractors for the docstring, keywords, CallPolicies, + // and default implementation of virtual functions + // + + template <class Tuple> + struct doc_extract + : tuple_extract< + Tuple + , mpl::not_< + mpl::or_< + indirect_traits::is_reference_to_class<mpl::_1> + , indirect_traits::is_reference_to_member_function_pointer<mpl::_1 > + > + > + > + { + }; + + template <class Tuple> + struct keyword_extract + : tuple_extract<Tuple, is_reference_to_keywords<mpl::_1 > > + { + }; + + template <class Tuple> + struct policy_extract + : tuple_extract< + Tuple + , mpl::and_< + mpl::not_<is_same<not_specified const&,mpl::_1> > + , indirect_traits::is_reference_to_class<mpl::_1 > + , mpl::not_<is_reference_to_keywords<mpl::_1 > > + > + > + { + }; + + template <class Tuple> + struct default_implementation_extract + : tuple_extract< + Tuple + , indirect_traits::is_reference_to_member_function_pointer<mpl::_1 > + > + { + }; + + // + // A helper class for decoding the optional arguments to def() + // invocations, which can be supplied in any order and are + // discriminated by their type properties. The template parameters + // are expected to be the types of the actual (optional) arguments + // passed to def(). + // + template <class T1, class T2, class T3, class T4> + struct def_helper + { + // A tuple type which begins with references to the supplied + // arguments and ends with actual representatives of the default + // types. + typedef boost::tuples::tuple< + T1 const& + , T2 const& + , T3 const& + , T4 const& + , default_call_policies + , detail::keywords<0> + , char const* + , void(not_specified::*)() // A function pointer type which is never an + // appropriate default implementation + > all_t; + + // Constructors; these initialize an member of the tuple type + // shown above. + def_helper(T1 const& a1) : m_all(a1,m_nil,m_nil,m_nil) {} + def_helper(T1 const& a1, T2 const& a2) : m_all(a1,a2,m_nil,m_nil) {} + def_helper(T1 const& a1, T2 const& a2, T3 const& a3) : m_all(a1,a2,a3,m_nil) {} + def_helper(T1 const& a1, T2 const& a2, T3 const& a3, T4 const& a4) : m_all(a1,a2,a3,a4) {} + + private: // types + typedef typename default_implementation_extract<all_t>::result_type default_implementation_t; + + public: // Constants which can be used for static assertions. + + // Users must not supply a default implementation for non-class + // methods. + BOOST_STATIC_CONSTANT( + bool, has_default_implementation = ( + !is_same<default_implementation_t, void(not_specified::*)()>::value)); + + public: // Extractor functions which pull the appropriate value out + // of the tuple + char const* doc() const + { + return doc_extract<all_t>::extract(m_all); + } + + typename keyword_extract<all_t>::result_type keywords() const + { + return keyword_extract<all_t>::extract(m_all); + } + + typename policy_extract<all_t>::result_type policies() const + { + return policy_extract<all_t>::extract(m_all); + } + + default_implementation_t default_implementation() const + { + return default_implementation_extract<all_t>::extract(m_all); + } + + private: // data members + all_t m_all; + not_specified m_nil; // for filling in not_specified slots + }; +} + +}} // namespace boost::python::detail + +#endif // DEF_HELPER_DWA200287_HPP diff --git a/boost/python/detail/def_helper_fwd.hpp b/boost/python/detail/def_helper_fwd.hpp new file mode 100644 index 0000000000..31c22e97a3 --- /dev/null +++ b/boost/python/detail/def_helper_fwd.hpp @@ -0,0 +1,17 @@ +// Copyright David Abrahams 2003. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef DEF_HELPER_FWD_DWA2003810_HPP +# define DEF_HELPER_FWD_DWA2003810_HPP + +# include <boost/python/detail/not_specified.hpp> + +namespace boost { namespace python { namespace detail { + +template <class T1, class T2 = not_specified, class T3 = not_specified, class T4 = not_specified> +struct def_helper; + +}}} // namespace boost::python::detail + +#endif // DEF_HELPER_FWD_DWA2003810_HPP diff --git a/boost/python/detail/defaults_def.hpp b/boost/python/detail/defaults_def.hpp new file mode 100644 index 0000000000..68799f83e6 --- /dev/null +++ b/boost/python/detail/defaults_def.hpp @@ -0,0 +1,291 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright David Abrahams 2002, Joel de Guzman, 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +/////////////////////////////////////////////////////////////////////////////// +#if !defined(BOOST_PP_IS_ITERATING) + +#ifndef DEFAULTS_DEF_JDG20020811_HPP +#define DEFAULTS_DEF_JDG20020811_HPP + +#include <boost/python/detail/defaults_gen.hpp> +#include <boost/type_traits.hpp> +#include <boost/mpl/front.hpp> +#include <boost/mpl/size.hpp> +#include <boost/static_assert.hpp> +#include <boost/preprocessor/iterate.hpp> +#include <boost/python/class_fwd.hpp> +#include <boost/python/scope.hpp> +#include <boost/preprocessor/debug/line.hpp> +#include <boost/python/detail/scope.hpp> +#include <boost/python/detail/make_keyword_range_fn.hpp> +#include <boost/python/object/add_to_namespace.hpp> + +/////////////////////////////////////////////////////////////////////////////// +namespace boost { namespace python { + +struct module; + +namespace objects +{ + struct class_base; +} + +namespace detail +{ + // Called as:: + // + // name_space_def(ns, "func", func, kw, policies, docstring, &ns) + // + // Dispatch to properly add f to namespace ns. + // + // @group define_stub_function helpers { + template <class Func, class CallPolicies, class NameSpaceT> + static void name_space_def( + NameSpaceT& name_space + , char const* name + , Func f + , keyword_range const& kw + , CallPolicies const& policies + , char const* doc + , objects::class_base* + ) + { + typedef typename NameSpaceT::wrapped_type wrapped_type; + + objects::add_to_namespace( + name_space, name, + detail::make_keyword_range_function( + f, policies, kw, get_signature(f, (wrapped_type*)0)) + , doc + ); + } + + template <class Func, class CallPolicies> + static void name_space_def( + object& name_space + , char const* name + , Func f + , keyword_range const& kw + , CallPolicies const& policies + , char const* doc + , ... + ) + { + scope within(name_space); + + detail::scope_setattr_doc( + name + , detail::make_keyword_range_function(f, policies, kw) + , doc); + } + + // For backward compatibility -- is this obsolete? + template <class Func, class CallPolicies, class NameSpaceT> + static void name_space_def( + NameSpaceT& name_space + , char const* name + , Func f + , keyword_range const& kw // ignored + , CallPolicies const& policies + , char const* doc + , module* + ) + { + name_space.def(name, f, policies, doc); + } + // } + + + // Expansions of :: + // + // template <typename OverloadsT, typename NameSpaceT> + // inline void + // define_stub_function( + // char const* name, OverloadsT s, NameSpaceT& name_space, mpl::int_<N>) + // { + // name_space.def(name, &OverloadsT::func_N); + // } + // + // where N runs from 0 to BOOST_PYTHON_MAX_ARITY. + // + // The set of overloaded functions (define_stub_function) expects: + // + // 1. char const* name: function name that will be visible to python + // 2. OverloadsT: a function overloads struct (see defaults_gen.hpp) + // 3. NameSpaceT& name_space: a python::class_ or python::module instance + // 4. int_t<N>: the Nth overloaded function (OverloadsT::func_N) + // (see defaults_gen.hpp) + // 5. char const* name: doc string + // + // @group define_stub_function<N> { + template <int N> + struct define_stub_function {}; + +#define BOOST_PP_ITERATION_PARAMS_1 \ + (3, (0, BOOST_PYTHON_MAX_ARITY, <boost/python/detail/defaults_def.hpp>)) + +#include BOOST_PP_ITERATE() + + // } + + // This helper template struct does the actual recursive + // definition. There's a generic version + // define_with_defaults_helper<N> and a terminal case + // define_with_defaults_helper<0>. The struct and its + // specialization has a sole static member function def that + // expects: + // + // 1. char const* name: function name that will be + // visible to python + // + // 2. OverloadsT: a function overloads struct + // (see defaults_gen.hpp) + // + // 3. NameSpaceT& name_space: a python::class_ or + // python::module instance + // + // 4. char const* name: doc string + // + // The def static member function calls a corresponding + // define_stub_function<N>. The general case recursively calls + // define_with_defaults_helper<N-1>::def until it reaches the + // terminal case case define_with_defaults_helper<0>. + template <int N> + struct define_with_defaults_helper { + + template <class StubsT, class CallPolicies, class NameSpaceT> + static void + def( + char const* name, + StubsT stubs, + keyword_range kw, + CallPolicies const& policies, + NameSpaceT& name_space, + char const* doc) + { + // define the NTH stub function of stubs + define_stub_function<N>::define(name, stubs, kw, policies, name_space, doc); + + if (kw.second > kw.first) + --kw.second; + + // call the next define_with_defaults_helper + define_with_defaults_helper<N-1>::def(name, stubs, kw, policies, name_space, doc); + } + }; + + template <> + struct define_with_defaults_helper<0> { + + template <class StubsT, class CallPolicies, class NameSpaceT> + static void + def( + char const* name, + StubsT stubs, + keyword_range const& kw, + CallPolicies const& policies, + NameSpaceT& name_space, + char const* doc) + { + // define the Oth stub function of stubs + define_stub_function<0>::define(name, stubs, kw, policies, name_space, doc); + // return + } + }; + + // define_with_defaults + // + // 1. char const* name: function name that will be + // visible to python + // + // 2. OverloadsT: a function overloads struct + // (see defaults_gen.hpp) + // + // 3. CallPolicies& policies: Call policies + // 4. NameSpaceT& name_space: a python::class_ or + // python::module instance + // + // 5. SigT sig: Function signature typelist + // (see defaults_gen.hpp) + // + // 6. char const* name: doc string + // + // This is the main entry point. This function recursively + // defines all stub functions of StubT (see defaults_gen.hpp) in + // NameSpaceT name_space which can be either a python::class_ or + // a python::module. The sig argument is a typelist that + // specifies the return type, the class (for member functions, + // and the arguments. Here are some SigT examples: + // + // int foo(int) mpl::vector<int, int> + // void bar(int, int) mpl::vector<void, int, int> + // void C::foo(int) mpl::vector<void, C, int> + // + template <class OverloadsT, class NameSpaceT, class SigT> + inline void + define_with_defaults( + char const* name, + OverloadsT const& overloads, + NameSpaceT& name_space, + SigT const&) + { + typedef typename mpl::front<SigT>::type return_type; + typedef typename OverloadsT::void_return_type void_return_type; + typedef typename OverloadsT::non_void_return_type non_void_return_type; + + typedef typename mpl::if_c< + boost::is_same<void, return_type>::value + , void_return_type + , non_void_return_type + >::type stubs_type; + + BOOST_STATIC_ASSERT( + (stubs_type::max_args) <= mpl::size<SigT>::value); + + typedef typename stubs_type::template gen<SigT> gen_type; + define_with_defaults_helper<stubs_type::n_funcs-1>::def( + name + , gen_type() + , overloads.keywords() + , overloads.call_policies() + , name_space + , overloads.doc_string()); + } + +} // namespace detail + +}} // namespace boost::python + +#endif // DEFAULTS_DEF_JDG20020811_HPP + +#else // defined(BOOST_PP_IS_ITERATING) +// PP vertical iteration code + + +template <> +struct define_stub_function<BOOST_PP_ITERATION()> { + template <class StubsT, class CallPolicies, class NameSpaceT> + static void define( + char const* name + , StubsT const& + , keyword_range const& kw + , CallPolicies const& policies + , NameSpaceT& name_space + , char const* doc) + { + detail::name_space_def( + name_space + , name + , &StubsT::BOOST_PP_CAT(func_, BOOST_PP_ITERATION()) + , kw + , policies + , doc + , &name_space); + } +}; + +#endif // !defined(BOOST_PP_IS_ITERATING) diff --git a/boost/python/detail/defaults_gen.hpp b/boost/python/detail/defaults_gen.hpp new file mode 100644 index 0000000000..0b3e0e2604 --- /dev/null +++ b/boost/python/detail/defaults_gen.hpp @@ -0,0 +1,388 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright David Abrahams 2002, Joel de Guzman, 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +/////////////////////////////////////////////////////////////////////////////// +#ifndef DEFAULTS_GEN_JDG20020807_HPP +#define DEFAULTS_GEN_JDG20020807_HPP + +#include <boost/python/detail/preprocessor.hpp> +#include <boost/preprocessor/repeat.hpp> +#include <boost/preprocessor/repeat_from_to.hpp> +#include <boost/preprocessor/enum.hpp> +#include <boost/preprocessor/enum_params.hpp> +#include <boost/preprocessor/repetition/enum_binary_params.hpp> +#include <boost/preprocessor/tuple.hpp> +#include <boost/preprocessor/cat.hpp> +#include <boost/preprocessor/arithmetic/sub.hpp> +#include <boost/preprocessor/stringize.hpp> +#include <boost/preprocessor/inc.hpp> +#include <boost/preprocessor/empty.hpp> +#include <boost/preprocessor/comma_if.hpp> +#include <boost/config.hpp> +#include <boost/mpl/begin_end.hpp> +#include <boost/mpl/next.hpp> +#include <boost/mpl/deref.hpp> +#include <cstddef> + +namespace boost { namespace python { + +namespace detail +{ + // overloads_base is used as a base class for all function + // stubs. This class holds the doc_string of the stubs. + struct overloads_base + { + overloads_base(char const* doc_) + : m_doc(doc_) {} + + overloads_base(char const* doc_, detail::keyword_range const& kw) + : m_doc(doc_), m_keywords(kw) {} + + char const* doc_string() const + { + return m_doc; + } + + detail::keyword_range const& keywords() const + { + return m_keywords; + } + + private: + char const* m_doc; + detail::keyword_range m_keywords; + }; + + // overloads_proxy is generated by the overloads_common operator[] (see + // below). This class holds a user defined call policies of the stubs. + template <class CallPoliciesT, class OverloadsT> + struct overloads_proxy + : public overloads_base + { + typedef typename OverloadsT::non_void_return_type non_void_return_type; + typedef typename OverloadsT::void_return_type void_return_type; + + overloads_proxy( + CallPoliciesT const& policies_ + , char const* doc + , keyword_range const& kw + ) + : overloads_base(doc, kw) + , policies(policies_) + {} + + CallPoliciesT + call_policies() const + { + return policies; + } + + CallPoliciesT policies; + }; + + // overloads_common is our default function stubs base class. This + // class returns the default_call_policies in its call_policies() + // member function. It can generate a overloads_proxy however through + // its operator[] + template <class DerivedT> + struct overloads_common + : public overloads_base + { + overloads_common(char const* doc) + : overloads_base(doc) {} + + overloads_common(char const* doc, keyword_range const& kw) + : overloads_base(doc, kw) {} + + default_call_policies + call_policies() const + { + return default_call_policies(); + } + + template <class CallPoliciesT> + overloads_proxy<CallPoliciesT, DerivedT> + operator[](CallPoliciesT const& policies) const + { + return overloads_proxy<CallPoliciesT, DerivedT>( + policies, this->doc_string(), this->keywords()); + } + }; + +}}} // namespace boost::python::detail + + +#define BOOST_PYTHON_TYPEDEF_GEN(z, index, data) \ + typedef typename ::boost::mpl::next<BOOST_PP_CAT(iter, index)>::type \ + BOOST_PP_CAT(iter, BOOST_PP_INC(index)); \ + typedef typename ::boost::mpl::deref<BOOST_PP_CAT(iter, index)>::type \ + BOOST_PP_CAT(T, index); + +#define BOOST_PYTHON_FUNC_WRAPPER_GEN(z, index, data) \ + static RT BOOST_PP_CAT(func_, \ + BOOST_PP_SUB_D(1, index, BOOST_PP_TUPLE_ELEM(3, 1, data))) ( \ + BOOST_PP_ENUM_BINARY_PARAMS_Z( \ + 1, index, T, arg)) \ + { \ + BOOST_PP_TUPLE_ELEM(3, 2, data) \ + BOOST_PP_TUPLE_ELEM(3, 0, data)( \ + BOOST_PP_ENUM_PARAMS( \ + index, \ + arg)); \ + } + +#define BOOST_PYTHON_GEN_FUNCTION(fname, fstubs_name, n_args, n_dflts, ret) \ + struct fstubs_name \ + { \ + BOOST_STATIC_CONSTANT(int, n_funcs = BOOST_PP_INC(n_dflts)); \ + BOOST_STATIC_CONSTANT(int, max_args = n_funcs); \ + \ + template <typename SigT> \ + struct gen \ + { \ + typedef typename ::boost::mpl::begin<SigT>::type rt_iter; \ + typedef typename ::boost::mpl::deref<rt_iter>::type RT; \ + typedef typename ::boost::mpl::next<rt_iter>::type iter0; \ + \ + BOOST_PP_REPEAT_2ND( \ + n_args, \ + BOOST_PYTHON_TYPEDEF_GEN, \ + 0) \ + \ + BOOST_PP_REPEAT_FROM_TO_2( \ + BOOST_PP_SUB_D(1, n_args, n_dflts), \ + BOOST_PP_INC(n_args), \ + BOOST_PYTHON_FUNC_WRAPPER_GEN, \ + (fname, BOOST_PP_SUB_D(1, n_args, n_dflts), ret)) \ + }; \ + }; \ + +/////////////////////////////////////////////////////////////////////////////// +#define BOOST_PYTHON_MEM_FUNC_WRAPPER_GEN(z, index, data) \ + static RT BOOST_PP_CAT(func_, \ + BOOST_PP_SUB_D(1, index, BOOST_PP_TUPLE_ELEM(3, 1, data))) ( \ + ClassT obj BOOST_PP_COMMA_IF(index) \ + BOOST_PP_ENUM_BINARY_PARAMS_Z(1, index, T, arg) \ + ) \ + { \ + BOOST_PP_TUPLE_ELEM(3, 2, data) obj.BOOST_PP_TUPLE_ELEM(3, 0, data)( \ + BOOST_PP_ENUM_PARAMS(index, arg) \ + ); \ + } + +#define BOOST_PYTHON_GEN_MEM_FUNCTION(fname, fstubs_name, n_args, n_dflts, ret) \ + struct fstubs_name \ + { \ + BOOST_STATIC_CONSTANT(int, n_funcs = BOOST_PP_INC(n_dflts)); \ + BOOST_STATIC_CONSTANT(int, max_args = n_funcs + 1); \ + \ + template <typename SigT> \ + struct gen \ + { \ + typedef typename ::boost::mpl::begin<SigT>::type rt_iter; \ + typedef typename ::boost::mpl::deref<rt_iter>::type RT; \ + \ + typedef typename ::boost::mpl::next<rt_iter>::type class_iter; \ + typedef typename ::boost::mpl::deref<class_iter>::type ClassT; \ + typedef typename ::boost::mpl::next<class_iter>::type iter0; \ + \ + BOOST_PP_REPEAT_2ND( \ + n_args, \ + BOOST_PYTHON_TYPEDEF_GEN, \ + 0) \ + \ + BOOST_PP_REPEAT_FROM_TO_2( \ + BOOST_PP_SUB_D(1, n_args, n_dflts), \ + BOOST_PP_INC(n_args), \ + BOOST_PYTHON_MEM_FUNC_WRAPPER_GEN, \ + (fname, BOOST_PP_SUB_D(1, n_args, n_dflts), ret)) \ + }; \ + }; + +#define BOOST_PYTHON_OVERLOAD_CONSTRUCTORS(fstubs_name, n_args, n_dflts) \ + fstubs_name(char const* doc = 0) \ + : ::boost::python::detail::overloads_common<fstubs_name>(doc) {} \ + template <std::size_t N> \ + fstubs_name(char const* doc, ::boost::python::detail::keywords<N> const& keywords) \ + : ::boost::python::detail::overloads_common<fstubs_name>( \ + doc, keywords.range()) \ + { \ + typedef typename ::boost::python::detail:: \ + error::more_keywords_than_function_arguments< \ + N,n_args>::too_many_keywords assertion; \ + } \ + template <std::size_t N> \ + fstubs_name(::boost::python::detail::keywords<N> const& keywords, char const* doc = 0) \ + : ::boost::python::detail::overloads_common<fstubs_name>( \ + doc, keywords.range()) \ + { \ + typedef typename ::boost::python::detail:: \ + error::more_keywords_than_function_arguments< \ + N,n_args>::too_many_keywords assertion; \ + } + +# if defined(BOOST_NO_VOID_RETURNS) + +# define BOOST_PYTHON_GEN_FUNCTION_STUB(fname, fstubs_name, n_args, n_dflts) \ + struct fstubs_name \ + : public ::boost::python::detail::overloads_common<fstubs_name> \ + { \ + BOOST_PYTHON_GEN_FUNCTION( \ + fname, non_void_return_type, n_args, n_dflts, return) \ + BOOST_PYTHON_GEN_FUNCTION( \ + fname, void_return_type, n_args, n_dflts, ;) \ + \ + BOOST_PYTHON_OVERLOAD_CONSTRUCTORS(fstubs_name, n_args, n_dflts) \ + }; + +# define BOOST_PYTHON_GEN_MEM_FUNCTION_STUB(fname, fstubs_name, n_args, n_dflts) \ + struct fstubs_name \ + : public ::boost::python::detail::overloads_common<fstubs_name> \ + { \ + BOOST_PYTHON_GEN_MEM_FUNCTION( \ + fname, non_void_return_type, n_args, n_dflts, return) \ + BOOST_PYTHON_GEN_MEM_FUNCTION( \ + fname, void_return_type, n_args, n_dflts, ;) \ + \ + BOOST_PYTHON_OVERLOAD_CONSTRUCTORS(fstubs_name, n_args + 1, n_dflts) \ + }; + +# else // !defined(BOOST_NO_VOID_RETURNS) + +# define BOOST_PYTHON_GEN_FUNCTION_STUB(fname, fstubs_name, n_args, n_dflts) \ + struct fstubs_name \ + : public ::boost::python::detail::overloads_common<fstubs_name> \ + { \ + BOOST_PYTHON_GEN_FUNCTION( \ + fname, non_void_return_type, n_args, n_dflts, return) \ + \ + typedef non_void_return_type void_return_type; \ + BOOST_PYTHON_OVERLOAD_CONSTRUCTORS(fstubs_name, n_args, n_dflts) \ + }; + + +# define BOOST_PYTHON_GEN_MEM_FUNCTION_STUB(fname, fstubs_name, n_args, n_dflts) \ + struct fstubs_name \ + : public ::boost::python::detail::overloads_common<fstubs_name> \ + { \ + BOOST_PYTHON_GEN_MEM_FUNCTION( \ + fname, non_void_return_type, n_args, n_dflts, return) \ + \ + typedef non_void_return_type void_return_type; \ + BOOST_PYTHON_OVERLOAD_CONSTRUCTORS(fstubs_name, n_args + 1, n_dflts) \ + }; + +# endif // !defined(BOOST_NO_VOID_RETURNS) + +/////////////////////////////////////////////////////////////////////////////// +// +// MAIN MACROS +// +// Given generator_name, fname, min_args and max_args, These macros +// generate function stubs that forward to a function or member function +// named fname. max_args is the arity of the function or member function +// fname. fname can have default arguments. min_args is the minimum +// arity that fname can accept. +// +// There are two versions: +// +// 1. BOOST_PYTHON_FUNCTION_OVERLOADS for free functions +// 2. BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS for member functions. +// +// For instance, given a function: +// +// int +// foo(int a, char b = 1, unsigned c = 2, double d = 3) +// { +// return a + b + c + int(d); +// } +// +// The macro invocation: +// +// BOOST_PYTHON_FUNCTION_OVERLOADS(foo_stubs, foo, 1, 4) +// +// Generates this code: +// +// struct foo_stubsNonVoid +// { +// static const int n_funcs = 4; +// static const int max_args = n_funcs; +// +// template <typename SigT> +// struct gen +// { +// typedef typename ::boost::mpl::begin<SigT>::type rt_iter; +// typedef typename rt_iter::type RT; +// typedef typename rt_iter::next iter0; +// typedef typename iter0::type T0; +// typedef typename iter0::next iter1; +// typedef typename iter1::type T1; +// typedef typename iter1::next iter2; +// typedef typename iter2::type T2; +// typedef typename iter2::next iter3; +// typedef typename iter3::type T3; +// typedef typename iter3::next iter4; +// +// static RT func_0(T0 arg0) +// { return foo(arg0); } +// +// static RT func_1(T0 arg0, T1 arg1) +// { return foo(arg0, arg1); } +// +// static RT func_2(T0 arg0, T1 arg1, T2 arg2) +// { return foo(arg0, arg1, arg2); } +// +// static RT func_3(T0 arg0, T1 arg1, T2 arg2, T3 arg3) +// { return foo(arg0, arg1, arg2, arg3); } +// }; +// }; +// +// struct foo_overloads +// : public boost::python::detail::overloads_common<foo_overloads> +// { +// typedef foo_overloadsNonVoid non_void_return_type; +// typedef foo_overloadsNonVoid void_return_type; +// +// foo_overloads(char const* doc = 0) +// : boost::python::detail::overloads_common<foo_overloads>(doc) {} +// }; +// +// The typedefs non_void_return_type and void_return_type are +// used to handle compilers that do not support void returns. The +// example above typedefs non_void_return_type and +// void_return_type to foo_overloadsNonVoid. On compilers that do +// not support void returns, there are two versions: +// foo_overloadsNonVoid and foo_overloadsVoid. The "Void" +// version is almost identical to the "NonVoid" version except +// for the return type (void) and the lack of the return keyword. +// +// See the overloads_common above for a description of the +// foo_overloads' base class. +// +/////////////////////////////////////////////////////////////////////////////// +#define BOOST_PYTHON_FUNCTION_OVERLOADS(generator_name, fname, min_args, max_args) \ + BOOST_PYTHON_GEN_FUNCTION_STUB( \ + fname, \ + generator_name, \ + max_args, \ + BOOST_PP_SUB_D(1, max_args, min_args)) + +#define BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(generator_name, fname, min_args, max_args) \ + BOOST_PYTHON_GEN_MEM_FUNCTION_STUB( \ + fname, \ + generator_name, \ + max_args, \ + BOOST_PP_SUB_D(1, max_args, min_args)) + +// deprecated macro names (to be removed) +#define BOOST_PYTHON_FUNCTION_GENERATOR BOOST_PYTHON_FUNCTION_OVERLOADS +#define BOOST_PYTHON_MEM_FUN_GENERATOR BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS + +/////////////////////////////////////////////////////////////////////////////// +#endif // DEFAULTS_GEN_JDG20020807_HPP + + diff --git a/boost/python/detail/dependent.hpp b/boost/python/detail/dependent.hpp new file mode 100644 index 0000000000..70392c4d78 --- /dev/null +++ b/boost/python/detail/dependent.hpp @@ -0,0 +1,27 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef DEPENDENT_DWA200286_HPP +# define DEPENDENT_DWA200286_HPP + +namespace boost { namespace python { namespace detail { + +// A way to turn a concrete type T into a type dependent on U. This +// keeps conforming compilers (those implementing proper 2-phase +// name lookup for templates) from complaining about incomplete +// types in situations where it would otherwise be inconvenient or +// impossible to re-order code so that all types are defined in time. + +// One such use is when we must return an incomplete T from a member +// function template (which must be defined in the class body to +// keep MSVC happy). +template <class T, class U> +struct dependent +{ + typedef T type; +}; + +}}} // namespace boost::python::detail + +#endif // DEPENDENT_DWA200286_HPP diff --git a/boost/python/detail/destroy.hpp b/boost/python/detail/destroy.hpp new file mode 100644 index 0000000000..0172dca28f --- /dev/null +++ b/boost/python/detail/destroy.hpp @@ -0,0 +1,106 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef DESTROY_DWA2002221_HPP +# define DESTROY_DWA2002221_HPP + +# include <boost/type_traits/is_array.hpp> +# include <boost/detail/workaround.hpp> +# if BOOST_WORKAROUND(BOOST_MSVC, == 1300) +# include <boost/type_traits/is_enum.hpp> +# endif +namespace boost { namespace python { namespace detail { + +template < + bool array +# if BOOST_WORKAROUND(BOOST_MSVC, == 1300) + , bool enum_ // vc7 has a problem destroying enums +# endif + > struct value_destroyer; + +template <> +struct value_destroyer< + false +# if BOOST_WORKAROUND(BOOST_MSVC, == 1300) + , false +# endif + > +{ + template <class T> + static void execute(T const volatile* p) + { + p->~T(); + } +}; + +template <> +struct value_destroyer< + true +# if BOOST_WORKAROUND(BOOST_MSVC, == 1300) + , false +# endif + > +{ + template <class A, class T> + static void execute(A*, T const volatile* const first) + { + for (T const volatile* p = first; p != first + sizeof(A)/sizeof(T); ++p) + { + value_destroyer< + boost::is_array<T>::value +# if BOOST_WORKAROUND(BOOST_MSVC, == 1300) + , boost::is_enum<T>::value +# endif + >::execute(p); + } + } + + template <class T> + static void execute(T const volatile* p) + { + execute(p, *p); + } +}; + +# if BOOST_WORKAROUND(BOOST_MSVC, == 1300) +template <> +struct value_destroyer<true,true> +{ + template <class T> + static void execute(T const volatile*) + { + } +}; + +template <> +struct value_destroyer<false,true> +{ + template <class T> + static void execute(T const volatile*) + { + } +}; +# endif +template <class T> +inline void destroy_referent_impl(void* p, T& (*)()) +{ + // note: cv-qualification needed for MSVC6 + // must come *before* T for metrowerks + value_destroyer< + (boost::is_array<T>::value) +# if BOOST_WORKAROUND(BOOST_MSVC, == 1300) + , (boost::is_enum<T>::value) +# endif + >::execute((const volatile T*)p); +} + +template <class T> +inline void destroy_referent(void* p, T(*)() = 0) +{ + destroy_referent_impl(p, (T(*)())0); +} + +}}} // namespace boost::python::detail + +#endif // DESTROY_DWA2002221_HPP diff --git a/boost/python/detail/enable_if.hpp b/boost/python/detail/enable_if.hpp new file mode 100644 index 0000000000..46a1d532b3 --- /dev/null +++ b/boost/python/detail/enable_if.hpp @@ -0,0 +1,72 @@ +// Copyright David Abrahams 2004. Distributed under the Boost +// Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +#ifndef ENABLE_IF_DWA2004722_HPP +# define ENABLE_IF_DWA2004722_HPP + +# include <boost/python/detail/sfinae.hpp> +# include <boost/detail/workaround.hpp> + +# if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) +# include <boost/mpl/if.hpp> + +namespace boost { namespace python { namespace detail { + +template <class T> struct always_void { typedef void type; }; + +template <class C, class T = int> +struct enable_if_arg +{ + typedef typename mpl::if_<C,T,int&>::type type; +}; + +template <class C, class T = int> +struct disable_if_arg +{ + typedef typename mpl::if_<C,int&,T>::type type; +}; + +template <class C, class T = typename always_void<C>::type> +struct enable_if_ret +{ + typedef typename mpl::if_<C,T,int[2]>::type type; +}; + +template <class C, class T = typename always_void<C>::type> +struct disable_if_ret +{ + typedef typename mpl::if_<C,int[2],T>::type type; +}; + +}}} // namespace boost::python::detail + +# elif !defined(BOOST_NO_SFINAE) +# include <boost/utility/enable_if.hpp> + +namespace boost { namespace python { namespace detail { + +template <class C, class T = int> +struct enable_if_arg + : enable_if<C,T> +{}; + +template <class C, class T = int> +struct disable_if_arg + : disable_if<C,T> +{}; + +template <class C, class T = void> +struct enable_if_ret + : enable_if<C,T> +{}; + +template <class C, class T = void> +struct disable_if_ret + : disable_if<C,T> +{}; + +}}} // namespace boost::python::detail + +# endif + +#endif // ENABLE_IF_DWA2004722_HPP diff --git a/boost/python/detail/exception_handler.hpp b/boost/python/detail/exception_handler.hpp new file mode 100644 index 0000000000..7f49868be6 --- /dev/null +++ b/boost/python/detail/exception_handler.hpp @@ -0,0 +1,48 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef EXCEPTION_HANDLER_DWA2002810_HPP +# define EXCEPTION_HANDLER_DWA2002810_HPP + +# include <boost/python/detail/config.hpp> +# include <boost/function/function0.hpp> +# include <boost/function/function2.hpp> + +namespace boost { namespace python { namespace detail { + +struct BOOST_PYTHON_DECL_FORWARD exception_handler; + +typedef function2<bool, exception_handler const&, function0<void> const&> handler_function; + +struct BOOST_PYTHON_DECL exception_handler +{ + private: // types + + public: + explicit exception_handler(handler_function const& impl); + + inline bool handle(function0<void> const& f) const; + + bool operator()(function0<void> const& f) const; + + static exception_handler* chain; + + private: + static exception_handler* tail; + + handler_function m_impl; + exception_handler* m_next; +}; + + +inline bool exception_handler::handle(function0<void> const& f) const +{ + return this->m_impl(*this, f); +} + +BOOST_PYTHON_DECL void register_exception_handler(handler_function const& f); + +}}} // namespace boost::python::detail + +#endif // EXCEPTION_HANDLER_DWA2002810_HPP diff --git a/boost/python/detail/force_instantiate.hpp b/boost/python/detail/force_instantiate.hpp new file mode 100644 index 0000000000..63e2874945 --- /dev/null +++ b/boost/python/detail/force_instantiate.hpp @@ -0,0 +1,32 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef FORCE_INSTANTIATE_DWA200265_HPP +# define FORCE_INSTANTIATE_DWA200265_HPP + +namespace boost { namespace python { namespace detail { + +// Allows us to force the argument to be instantiated without +// incurring unused variable warnings + +# if !defined(BOOST_MSVC) || BOOST_MSVC < 1300 || _MSC_FULL_VER > 13102196 + +template <class T> +inline void force_instantiate(T const&) {} + +# else + +# pragma optimize("g", off) +inline void force_instantiate_impl(...) {} +# pragma optimize("", on) +template <class T> +inline void force_instantiate(T const& x) +{ + detail::force_instantiate_impl(&x); +} +# endif + +}}} // namespace boost::python::detail + +#endif // FORCE_INSTANTIATE_DWA200265_HPP diff --git a/boost/python/detail/if_else.hpp b/boost/python/detail/if_else.hpp new file mode 100644 index 0000000000..244e63a8ae --- /dev/null +++ b/boost/python/detail/if_else.hpp @@ -0,0 +1,116 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef IF_ELSE_DWA2002322_HPP +# define IF_ELSE_DWA2002322_HPP +# include <boost/config.hpp> + +namespace boost { namespace python { namespace detail { + +template <class T> struct elif_selected; + +template <class T> +struct if_selected +{ + template <bool b> + struct elif : elif_selected<T> + { + }; + + template <class U> + struct else_ + { + typedef T type; + }; +}; + +# if defined(BOOST_MSVC) && (BOOST_MSVC == 1300) +namespace msvc70_aux { + +template< bool > struct inherit_from +{ + template< typename T > struct result + { + typedef T type; + }; +}; + +template<> struct inherit_from<true> +{ + template< typename T > struct result + { + struct type {}; + }; +}; + +template< typename T > +struct never_true +{ + BOOST_STATIC_CONSTANT(bool, value = false); +}; + +} // namespace msvc70_aux + +#endif // # if defined(BOOST_MSVC) && (BOOST_MSVC == 1300) + +template <class T> +struct elif_selected +{ +# if !(defined(BOOST_MSVC) && BOOST_MSVC <= 1300 || defined(__MWERKS__) && __MWERKS__ <= 0x2407) + template <class U> class then; +# elif defined(BOOST_MSVC) && (BOOST_MSVC == 1300) + template <class U> + struct then : msvc70_aux::inherit_from< msvc70_aux::never_true<U>::value > + ::template result< if_selected<T> >::type + { + }; +# else + template <class U> + struct then : if_selected<T> + { + }; +# endif +}; + +# if !(defined(BOOST_MSVC) && BOOST_MSVC <= 1300 || defined(__MWERKS__) && __MWERKS__ <= 0x2407) +template <class T> +template <class U> +class elif_selected<T>::then : public if_selected<T> +{ +}; +# endif + +template <bool b> struct if_ +{ + template <class T> + struct then : if_selected<T> + { + }; +}; + +struct if_unselected +{ + template <bool b> struct elif : if_<b> + { + }; + + template <class U> + struct else_ + { + typedef U type; + }; +}; + +template <> +struct if_<false> +{ + template <class T> + struct then : if_unselected + { + }; +}; + +}}} // namespace boost::python::detail + +#endif // IF_ELSE_DWA2002322_HPP diff --git a/boost/python/detail/indirect_traits.hpp b/boost/python/detail/indirect_traits.hpp new file mode 100644 index 0000000000..ce8ba310a2 --- /dev/null +++ b/boost/python/detail/indirect_traits.hpp @@ -0,0 +1,13 @@ +// Copyright David Abrahams 2004. Distributed under the Boost +// Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +#ifndef INDIRECT_TRAITS_DWA2004915_HPP +# define INDIRECT_TRAITS_DWA2004915_HPP + +# include <boost/detail/indirect_traits.hpp> + +namespace boost { namespace python { +namespace indirect_traits = boost::detail::indirect_traits; +}} // namespace boost::python::detail + +#endif // INDIRECT_TRAITS_DWA2004915_HPP diff --git a/boost/python/detail/invoke.hpp b/boost/python/detail/invoke.hpp new file mode 100644 index 0000000000..939fa11818 --- /dev/null +++ b/boost/python/detail/invoke.hpp @@ -0,0 +1,100 @@ +#if !defined(BOOST_PP_IS_ITERATING) + +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +# ifndef INVOKE_DWA20021122_HPP +# define INVOKE_DWA20021122_HPP + +# include <boost/python/detail/prefix.hpp> +# include <boost/python/detail/preprocessor.hpp> +# include <boost/python/detail/none.hpp> + +# include <boost/type_traits/is_member_function_pointer.hpp> + +# include <boost/preprocessor/iterate.hpp> +# include <boost/preprocessor/facilities/intercept.hpp> +# include <boost/preprocessor/repetition/enum_trailing_params.hpp> +# include <boost/preprocessor/repetition/enum_trailing_binary_params.hpp> +# include <boost/preprocessor/repetition/enum_binary_params.hpp> +# include <boost/python/to_python_value.hpp> + +// This file declares a series of overloaded invoke(...) functions, +// used to invoke wrapped C++ function (object)s from Python. Each one +// accepts: +// +// - a tag which identifies the invocation syntax (e.g. member +// functions must be invoked with a different syntax from regular +// functions) +// +// - a pointer to a result converter type, used solely as a way of +// transmitting the type of the result converter to the function (or +// an int, if the return type is void). +// +// - the "function", which may be a function object, a function or +// member function pointer, or a defaulted_virtual_fn. +// +// - The arg_from_python converters for each of the arguments to be +// passed to the function being invoked. + +namespace boost { namespace python { namespace detail { + +// This "result converter" is really just used as a dispatch tag to +// invoke(...), selecting the appropriate implementation +typedef int void_result_to_python; + +template <bool void_return, bool member> +struct invoke_tag_ {}; + +// A metafunction returning the appropriate tag type for invoking an +// object of type F with return type R. +template <class R, class F> +struct invoke_tag + : invoke_tag_< + is_same<R,void>::value + , is_member_function_pointer<F>::value + > +{ +}; + +# define BOOST_PP_ITERATION_PARAMS_1 \ + (3, (0, BOOST_PYTHON_MAX_ARITY, <boost/python/detail/invoke.hpp>)) +# include BOOST_PP_ITERATE() + +}}} // namespace boost::python::detail + +# endif // INVOKE_DWA20021122_HPP +#else + +# define N BOOST_PP_ITERATION() + +template <class RC, class F BOOST_PP_ENUM_TRAILING_PARAMS_Z(1, N, class AC)> +inline PyObject* invoke(invoke_tag_<false,false>, RC const& rc, F& f BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_Z(1, N, AC, & ac) ) +{ + return rc(f( BOOST_PP_ENUM_BINARY_PARAMS_Z(1, N, ac, () BOOST_PP_INTERCEPT) )); +} + +template <class RC, class F BOOST_PP_ENUM_TRAILING_PARAMS_Z(1, N, class AC)> +inline PyObject* invoke(invoke_tag_<true,false>, RC const&, F& f BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_Z(1, N, AC, & ac) ) +{ + f( BOOST_PP_ENUM_BINARY_PARAMS_Z(1, N, ac, () BOOST_PP_INTERCEPT) ); + return none(); +} + +template <class RC, class F, class TC BOOST_PP_ENUM_TRAILING_PARAMS_Z(1, N, class AC)> +inline PyObject* invoke(invoke_tag_<false,true>, RC const& rc, F& f, TC& tc BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_Z(1, N, AC, & ac) ) +{ + return rc( (tc().*f)(BOOST_PP_ENUM_BINARY_PARAMS_Z(1, N, ac, () BOOST_PP_INTERCEPT)) ); +} + +template <class RC, class F, class TC BOOST_PP_ENUM_TRAILING_PARAMS_Z(1, N, class AC)> +inline PyObject* invoke(invoke_tag_<true,true>, RC const&, F& f, TC& tc BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_Z(1, N, AC, & ac) ) +{ + (tc().*f)(BOOST_PP_ENUM_BINARY_PARAMS_Z(1, N, ac, () BOOST_PP_INTERCEPT)); + return none(); +} + +# undef N + +#endif // BOOST_PP_IS_ITERATING diff --git a/boost/python/detail/is_auto_ptr.hpp b/boost/python/detail/is_auto_ptr.hpp new file mode 100644 index 0000000000..3b8198b8dd --- /dev/null +++ b/boost/python/detail/is_auto_ptr.hpp @@ -0,0 +1,30 @@ +// Copyright David Abrahams 2003. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef IS_AUTO_PTR_DWA2003224_HPP +# define IS_AUTO_PTR_DWA2003224_HPP + +# ifndef BOOST_NO_AUTO_PTR +# include <boost/python/detail/is_xxx.hpp> +# include <memory> +# endif + +namespace boost { namespace python { namespace detail { + +# if !defined(BOOST_NO_AUTO_PTR) + +BOOST_PYTHON_IS_XXX_DEF(auto_ptr, std::auto_ptr, 1) + +# else + +template <class T> +struct is_auto_ptr : mpl::false_ +{ +}; + +# endif + +}}} // namespace boost::python::detail + +#endif // IS_AUTO_PTR_DWA2003224_HPP diff --git a/boost/python/detail/is_shared_ptr.hpp b/boost/python/detail/is_shared_ptr.hpp new file mode 100644 index 0000000000..547af3f1cb --- /dev/null +++ b/boost/python/detail/is_shared_ptr.hpp @@ -0,0 +1,17 @@ +// Copyright David Abrahams 2003. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef IS_SHARED_PTR_DWA2003224_HPP +# define IS_SHARED_PTR_DWA2003224_HPP + +# include <boost/python/detail/is_xxx.hpp> +# include <boost/shared_ptr.hpp> + +namespace boost { namespace python { namespace detail { + +BOOST_PYTHON_IS_XXX_DEF(shared_ptr, shared_ptr, 1) + +}}} // namespace boost::python::detail + +#endif // IS_SHARED_PTR_DWA2003224_HPP diff --git a/boost/python/detail/is_wrapper.hpp b/boost/python/detail/is_wrapper.hpp new file mode 100644 index 0000000000..d7bce7b627 --- /dev/null +++ b/boost/python/detail/is_wrapper.hpp @@ -0,0 +1,29 @@ +// Copyright David Abrahams 2004. Distributed under the Boost +// Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +#ifndef IS_WRAPPER_DWA2004723_HPP +# define IS_WRAPPER_DWA2004723_HPP + +# include <boost/python/detail/prefix.hpp> +# include <boost/mpl/bool.hpp> + +namespace boost { namespace python { + +template <class T> class wrapper; + +namespace detail +{ + typedef char (&is_not_wrapper)[2]; + is_not_wrapper is_wrapper_helper(...); + template <class T> + char is_wrapper_helper(wrapper<T> const volatile*); + + // A metafunction returning true iff T is [derived from] wrapper<U> + template <class T> + struct is_wrapper + : mpl::bool_<(sizeof(detail::is_wrapper_helper((T*)0)) == 1)> + {}; + +}}} // namespace boost::python::detail + +#endif // IS_WRAPPER_DWA2004723_HPP diff --git a/boost/python/detail/is_xxx.hpp b/boost/python/detail/is_xxx.hpp new file mode 100644 index 0000000000..9ddfafd3c0 --- /dev/null +++ b/boost/python/detail/is_xxx.hpp @@ -0,0 +1,13 @@ +// Copyright David Abrahams 2005. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef IS_XXX_DWA2003224_HPP +# define IS_XXX_DWA2003224_HPP + +# include <boost/detail/is_xxx.hpp> + +# define BOOST_PYTHON_IS_XXX_DEF(name, qualified_name, nargs) \ + BOOST_DETAIL_IS_XXX_DEF(name, qualified_name, nargs) + +#endif // IS_XXX_DWA2003224_HPP diff --git a/boost/python/detail/make_keyword_range_fn.hpp b/boost/python/detail/make_keyword_range_fn.hpp new file mode 100644 index 0000000000..c4795cf887 --- /dev/null +++ b/boost/python/detail/make_keyword_range_fn.hpp @@ -0,0 +1,72 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef MAKE_KEYWORD_RANGE_FN_DWA2002927_HPP +# define MAKE_KEYWORD_RANGE_FN_DWA2002927_HPP + +# include <boost/python/make_function.hpp> +# include <boost/python/args_fwd.hpp> + +# include <boost/python/object/make_holder.hpp> + +# include <boost/mpl/size.hpp> + + +namespace boost { namespace python { namespace detail { + +// Think of this as a version of make_function without a compile-time +// check that the size of kw is no greater than the expected arity of +// F. This version is needed when defining functions with default +// arguments, because compile-time information about the number of +// keywords is missing for all but the initial function definition. +// +// @group make_keyword_range_function { +template <class F, class Policies> +object make_keyword_range_function( + F f + , Policies const& policies + , keyword_range const& kw) +{ + return detail::make_function_aux( + f, policies, detail::get_signature(f), kw, mpl::int_<0>()); +} + +template <class F, class Policies, class Signature> +object make_keyword_range_function( + F f + , Policies const& policies + , keyword_range const& kw + , Signature const& sig) +{ + return detail::make_function_aux( + f, policies, sig, kw, mpl::int_<0>()); +} +// } + +// Builds an '__init__' function which inserts the given Holder type +// in a wrapped C++ class instance. ArgList is an MPL type sequence +// describing the C++ argument types to be passed to Holder's +// constructor. +// +// Holder and ArgList are intended to be explicitly specified. +template <class ArgList, class Arity, class Holder, class CallPolicies> +object make_keyword_range_constructor( + CallPolicies const& policies // The CallPolicies with which to invoke the Holder's constructor + , detail::keyword_range const& kw // The (possibly empty) set of associated argument keywords + , Holder* = 0 + , ArgList* = 0, Arity* = 0) +{ +#if !defined( BOOST_PYTHON_NO_PY_SIGNATURES) && defined( BOOST_PYTHON_PY_SIGNATURES_PROPER_INIT_SELF_TYPE) + python_class<BOOST_DEDUCED_TYPENAME Holder::value_type>::register_(); +#endif + return detail::make_keyword_range_function( + objects::make_holder<Arity::value> + ::template apply<Holder,ArgList>::execute + , policies + , kw); +} + +}}} // namespace boost::python::detail + +#endif // MAKE_KEYWORD_RANGE_FN_DWA2002927_HPP diff --git a/boost/python/detail/make_tuple.hpp b/boost/python/detail/make_tuple.hpp new file mode 100644 index 0000000000..57b285be1c --- /dev/null +++ b/boost/python/detail/make_tuple.hpp @@ -0,0 +1,32 @@ +# ifndef BOOST_PYTHON_SYNOPSIS +# // Copyright David Abrahams 2002. +# // Distributed under the Boost Software License, Version 1.0. (See +# // accompanying file LICENSE_1_0.txt or copy at +# // http://www.boost.org/LICENSE_1_0.txt) + +# if !defined(BOOST_PP_IS_ITERATING) +# error Boost.Python - do not include this file! +# endif + +# define N BOOST_PP_ITERATION() + +# define BOOST_PYTHON_MAKE_TUPLE_ARG(z, N, ignored) \ + PyTuple_SET_ITEM( \ + result.ptr() \ + , N \ + , python::incref(python::object(a##N).ptr()) \ + ); + + template <BOOST_PP_ENUM_PARAMS_Z(1, N, class A)> + tuple + make_tuple(BOOST_PP_ENUM_BINARY_PARAMS_Z(1, N, A, const& a)) + { + tuple result((detail::new_reference)::PyTuple_New(N)); + BOOST_PP_REPEAT_1ST(N, BOOST_PYTHON_MAKE_TUPLE_ARG, _) + return result; + } + +# undef BOOST_PYTHON_MAKE_TUPLE_ARG + +# undef N +# endif // BOOST_PYTHON_SYNOPSIS diff --git a/boost/python/detail/map_entry.hpp b/boost/python/detail/map_entry.hpp new file mode 100644 index 0000000000..8bf1759f9f --- /dev/null +++ b/boost/python/detail/map_entry.hpp @@ -0,0 +1,43 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef MAP_ENTRY_DWA2002118_HPP +# define MAP_ENTRY_DWA2002118_HPP + +namespace boost { namespace python { namespace detail { + +// A trivial type that works well as the value_type of associative +// vector maps +template <class Key, class Value> +struct map_entry +{ + map_entry() {} + map_entry(Key k) : key(k), value() {} + map_entry(Key k, Value v) : key(k), value(v) {} + + bool operator<(map_entry const& rhs) const + { + return this->key < rhs.key; + } + + Key key; + Value value; +}; + +template <class Key, class Value> +bool operator<(map_entry<Key,Value> const& e, Key const& k) +{ + return e.key < k; +} + +template <class Key, class Value> +bool operator<(Key const& k, map_entry<Key,Value> const& e) +{ + return k < e.key; +} + + +}}} // namespace boost::python::detail + +#endif // MAP_ENTRY_DWA2002118_HPP diff --git a/boost/python/detail/mpl_lambda.hpp b/boost/python/detail/mpl_lambda.hpp new file mode 100644 index 0000000000..a20608e710 --- /dev/null +++ b/boost/python/detail/mpl_lambda.hpp @@ -0,0 +1,12 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef MPL_LAMBDA_DWA2002122_HPP +# define MPL_LAMBDA_DWA2002122_HPP + +// this header should go away soon +# include <boost/mpl/aux_/lambda_support.hpp> +# define BOOST_PYTHON_MPL_LAMBDA_SUPPORT BOOST_MPL_AUX_LAMBDA_SUPPORT + +#endif // MPL_LAMBDA_DWA2002122_HPP diff --git a/boost/python/detail/msvc_typeinfo.hpp b/boost/python/detail/msvc_typeinfo.hpp new file mode 100644 index 0000000000..10f845058a --- /dev/null +++ b/boost/python/detail/msvc_typeinfo.hpp @@ -0,0 +1,75 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef MSVC_TYPEINFO_DWA200222_HPP +# define MSVC_TYPEINFO_DWA200222_HPP + +#include <typeinfo> +#include <boost/type.hpp> +#include <boost/type_traits/config.hpp> + +// +// Fix for MSVC's broken typeid() implementation which doesn't strip +// decoration. This fix doesn't handle cv-qualified array types. It +// could probably be done, but I haven't figured it out yet. +// + +# if defined(BOOST_MSVC) && BOOST_MSVC <= 1300 || defined(BOOST_INTEL_CXX_VERSION) && BOOST_INTEL_CXX_VERSION <= 700 + +namespace boost { namespace python { namespace detail { + +typedef std::type_info const& typeinfo; + +template <class T> +static typeinfo typeid_nonref(T const volatile*) { return typeid(T); } + +template <class T> +inline typeinfo typeid_ref_1(T&(*)()) +{ + return detail::typeid_nonref((T*)0); +} + +// A non-reference +template <class T> +inline typeinfo typeid_ref(type<T>*, T&(*)(type<T>)) +{ + return detail::typeid_nonref((T*)0); +} + +// A reference +template <class T> +inline typeinfo typeid_ref(type<T>*, ...) +{ + return detail::typeid_ref_1((T(*)())0); +} + +template< typename T > T&(* is_ref_tester1(type<T>) )(type<T>) { return 0; } +inline char BOOST_TT_DECL is_ref_tester1(...) { return 0; } + +template <class T> +inline typeinfo msvc_typeid(boost::type<T>*) +{ + return detail::typeid_ref( + (boost::type<T>*)0, detail::is_ref_tester1(type<T>()) + ); +} + +template <> +inline typeinfo msvc_typeid<void>(boost::type<void>*) +{ + return typeid(void); +} + +# ifndef NDEBUG +inline typeinfo assert_array_typeid_compiles() +{ + return msvc_typeid((boost::type<char const[3]>*)0) + , msvc_typeid((boost::type<char[3]>*)0); +} +# endif + +}}} // namespace boost::python::detail + +# endif // BOOST_MSVC +#endif // MSVC_TYPEINFO_DWA200222_HPP diff --git a/boost/python/detail/none.hpp b/boost/python/detail/none.hpp new file mode 100644 index 0000000000..bc3337a234 --- /dev/null +++ b/boost/python/detail/none.hpp @@ -0,0 +1,20 @@ +// (C) Copyright David Abrahams 2000. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// The author gratefully acknowleges the support of Dragon Systems, Inc., in +// producing this work. + +#ifndef NONE_DWA_052000_H_ +# define NONE_DWA_052000_H_ + +# include <boost/python/detail/prefix.hpp> + +namespace boost { namespace python { namespace detail { + +inline PyObject* none() { Py_INCREF(Py_None); return Py_None; } + +}}} // namespace boost::python::detail + +#endif // NONE_DWA_052000_H_ diff --git a/boost/python/detail/not_specified.hpp b/boost/python/detail/not_specified.hpp new file mode 100644 index 0000000000..2f7c7ad997 --- /dev/null +++ b/boost/python/detail/not_specified.hpp @@ -0,0 +1,14 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef NOT_SPECIFIED_DWA2002321_HPP +# define NOT_SPECIFIED_DWA2002321_HPP + +namespace boost { namespace python { namespace detail { + + struct not_specified {}; + +}}} // namespace boost::python::detail + +#endif // NOT_SPECIFIED_DWA2002321_HPP diff --git a/boost/python/detail/nullary_function_adaptor.hpp b/boost/python/detail/nullary_function_adaptor.hpp new file mode 100644 index 0000000000..9dcc434f8e --- /dev/null +++ b/boost/python/detail/nullary_function_adaptor.hpp @@ -0,0 +1,46 @@ +// Copyright David Abrahams 2003. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef NULLARY_FUNCTION_ADAPTOR_DWA2003824_HPP +# define NULLARY_FUNCTION_ADAPTOR_DWA2003824_HPP + +# include <boost/python/detail/prefix.hpp> +# include <boost/preprocessor/iteration/local.hpp> +# include <boost/preprocessor/facilities/intercept.hpp> +# include <boost/preprocessor/repetition/enum_params.hpp> +# include <boost/preprocessor/repetition/enum_binary_params.hpp> + +namespace boost { namespace python { namespace detail { + +// nullary_function_adaptor -- a class template which ignores its +// arguments and calls a nullary function instead. Used for building +// error-reporting functions, c.f. pure_virtual +template <class NullaryFunction> +struct nullary_function_adaptor +{ + nullary_function_adaptor(NullaryFunction fn) + : m_fn(fn) + {} + + void operator()() const { m_fn(); } + +# define BOOST_PP_LOCAL_MACRO(i) \ + template <BOOST_PP_ENUM_PARAMS_Z(1, i, class A)> \ + void operator()( \ + BOOST_PP_ENUM_BINARY_PARAMS_Z(1, i, A, const& BOOST_PP_INTERCEPT) \ + ) const \ + { \ + m_fn(); \ + } + +# define BOOST_PP_LOCAL_LIMITS (1, BOOST_PYTHON_MAX_ARITY) +# include BOOST_PP_LOCAL_ITERATE() + + private: + NullaryFunction m_fn; +}; + +}}} // namespace boost::python::detail + +#endif // NULLARY_FUNCTION_ADAPTOR_DWA2003824_HPP diff --git a/boost/python/detail/operator_id.hpp b/boost/python/detail/operator_id.hpp new file mode 100644 index 0000000000..ecfc70f108 --- /dev/null +++ b/boost/python/detail/operator_id.hpp @@ -0,0 +1,63 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef OPERATOR_ID_DWA2002531_HPP +# define OPERATOR_ID_DWA2002531_HPP + +namespace boost { namespace python { namespace detail { + +enum operator_id +{ + op_add, + op_sub, + op_mul, + op_div, + op_mod, + op_divmod, + op_pow, + op_lshift, + op_rshift, + op_and, + op_xor, + op_or, + op_neg, + op_pos, + op_abs, + op_invert, + op_int, + op_long, + op_float, + op_str, + op_cmp, + op_gt, + op_ge, + op_lt, + op_le, + op_eq, + op_ne, + op_iadd, + op_isub, + op_imul, + op_idiv, + op_imod, + op_ilshift, + op_irshift, + op_iand, + op_ixor, + op_ior, + op_complex, +#if PY_VERSION_HEX >= 0x03000000 + op_bool, +#else + op_nonzero, +#endif + op_repr +#if PY_VERSION_HEX >= 0x03000000 + ,op_truediv +#endif +}; + +}}} // namespace boost::python::detail + +#endif // OPERATOR_ID_DWA2002531_HPP diff --git a/boost/python/detail/overloads_fwd.hpp b/boost/python/detail/overloads_fwd.hpp new file mode 100644 index 0000000000..4c7fdf292b --- /dev/null +++ b/boost/python/detail/overloads_fwd.hpp @@ -0,0 +1,18 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef OVERLOADS_FWD_DWA2002101_HPP +# define OVERLOADS_FWD_DWA2002101_HPP + +namespace boost { namespace python { namespace detail { + +// forward declarations +struct overloads_base; + +template <class OverloadsT, class NameSpaceT, class SigT> +inline void define_with_defaults(char const* name, OverloadsT const&, NameSpaceT&, SigT const&); + +}}} // namespace boost::python::detail + +#endif // OVERLOADS_FWD_DWA2002101_HPP diff --git a/boost/python/detail/pointee.hpp b/boost/python/detail/pointee.hpp new file mode 100644 index 0000000000..e18c1f49b6 --- /dev/null +++ b/boost/python/detail/pointee.hpp @@ -0,0 +1,35 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef POINTEE_DWA2002323_HPP +# define POINTEE_DWA2002323_HPP + +# include <boost/type_traits/object_traits.hpp> + +namespace boost { namespace python { namespace detail { + +template <bool is_ptr = true> +struct pointee_impl +{ + template <class T> struct apply : remove_pointer<T> {}; +}; + +template <> +struct pointee_impl<false> +{ + template <class T> struct apply + { + typedef typename T::element_type type; + }; +}; + +template <class T> +struct pointee + : pointee_impl<is_pointer<T>::value>::template apply<T> +{ +}; + +}}} // namespace boost::python::detail + +#endif // POINTEE_DWA2002323_HPP diff --git a/boost/python/detail/prefix.hpp b/boost/python/detail/prefix.hpp new file mode 100644 index 0000000000..8b34ed7701 --- /dev/null +++ b/boost/python/detail/prefix.hpp @@ -0,0 +1,16 @@ +// Copyright David Abrahams 2003. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef PREFIX_DWA2003531_HPP +# define PREFIX_DWA2003531_HPP + +// The rule is that <Python.h> must be included before any system +// headers (so it can get control over some awful macros). +// Unfortunately, Boost.Python needs to #include <limits.h> first, at +// least... but this gets us as close as possible. + +# include <boost/python/detail/wrap_python.hpp> +# include <boost/python/detail/config.hpp> + +#endif // PREFIX_DWA2003531_HPP diff --git a/boost/python/detail/preprocessor.hpp b/boost/python/detail/preprocessor.hpp new file mode 100644 index 0000000000..2c1b2e84ea --- /dev/null +++ b/boost/python/detail/preprocessor.hpp @@ -0,0 +1,66 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef PREPROCESSOR_DWA200247_HPP +# define PREPROCESSOR_DWA200247_HPP + +# include <boost/preprocessor/cat.hpp> +# include <boost/preprocessor/comma_if.hpp> +# include <boost/preprocessor/repeat.hpp> +# include <boost/preprocessor/tuple/elem.hpp> + +// stuff that should be in the preprocessor library + +# define BOOST_PYTHON_APPLY(x) BOOST_PP_CAT(BOOST_PYTHON_APPLY_, x) + +# define BOOST_PYTHON_APPLY_BOOST_PYTHON_ITEM(v) v +# define BOOST_PYTHON_APPLY_BOOST_PYTHON_NIL + +// cv-qualifiers + +# if !defined(__MWERKS__) || __MWERKS__ > 0x2407 +# define BOOST_PYTHON_CV_COUNT 4 +# else +# define BOOST_PYTHON_CV_COUNT 1 +# endif + +# ifndef BOOST_PYTHON_MAX_ARITY +# define BOOST_PYTHON_MAX_ARITY 15 +# endif + +# ifndef BOOST_PYTHON_MAX_BASES +# define BOOST_PYTHON_MAX_BASES 10 +# endif + +# define BOOST_PYTHON_CV_QUALIFIER(i) \ + BOOST_PYTHON_APPLY( \ + BOOST_PP_TUPLE_ELEM(4, i, BOOST_PYTHON_CV_QUALIFIER_I) \ + ) + +# define BOOST_PYTHON_CV_QUALIFIER_I \ + ( \ + BOOST_PYTHON_NIL, \ + BOOST_PYTHON_ITEM(const), \ + BOOST_PYTHON_ITEM(volatile), \ + BOOST_PYTHON_ITEM(const volatile) \ + ) + +// enumerators +# define BOOST_PYTHON_UNARY_ENUM(c, text) BOOST_PP_REPEAT(c, BOOST_PYTHON_UNARY_ENUM_I, text) +# define BOOST_PYTHON_UNARY_ENUM_I(z, n, text) BOOST_PP_COMMA_IF(n) text ## n + +# define BOOST_PYTHON_BINARY_ENUM(c, a, b) BOOST_PP_REPEAT(c, BOOST_PYTHON_BINARY_ENUM_I, (a, b)) +# define BOOST_PYTHON_BINARY_ENUM_I(z, n, _) BOOST_PP_COMMA_IF(n) BOOST_PP_CAT(BOOST_PP_TUPLE_ELEM(2, 0, _), n) BOOST_PP_CAT(BOOST_PP_TUPLE_ELEM(2, 1, _), n) + +# define BOOST_PYTHON_ENUM_WITH_DEFAULT(c, text, def) BOOST_PP_REPEAT(c, BOOST_PYTHON_ENUM_WITH_DEFAULT_I, (text, def)) +# define BOOST_PYTHON_ENUM_WITH_DEFAULT_I(z, n, _) BOOST_PP_COMMA_IF(n) BOOST_PP_CAT(BOOST_PP_TUPLE_ELEM(2, 0, _), n) = BOOST_PP_TUPLE_ELEM(2, 1, _) + +// fixed text (no commas) +# define BOOST_PYTHON_FIXED(z, n, text) text + +// flags +# define BOOST_PYTHON_FUNCTION_POINTER 0x0001 +# define BOOST_PYTHON_POINTER_TO_MEMBER 0x0002 + +#endif // PREPROCESSOR_DWA200247_HPP diff --git a/boost/python/detail/python22_fixed.h b/boost/python/detail/python22_fixed.h new file mode 100644 index 0000000000..32bf941fef --- /dev/null +++ b/boost/python/detail/python22_fixed.h @@ -0,0 +1,152 @@ +// This file is a modified version of Python 2.2/2.2.1 Python.h. As +// such it is: +// +// Copyright (c) 2001, 2002 Python Software Foundation; All Rights +// Reserved +// +// boostinspect:nolicense (don't complain about the lack of a Boost license) +// +// Changes from the original: +// 1. #includes <unistd.h> for Python 2.2.1 +// 2. Provides missing extern "C" wrapper for "iterobject.h" and "descrobject.h". +// + +// Changes marked with "Boost.Python modification" +#ifndef Py_PYTHON_H +#define Py_PYTHON_H +/* Since this is a "meta-include" file, no #ifdef __cplusplus / extern "C" { */ + + +/* Enable compiler features; switching on C lib defines doesn't work + here, because the symbols haven't necessarily been defined yet. */ +#ifndef _GNU_SOURCE +# define _GNU_SOURCE 1 +#endif + +/* Forcing SUSv2 compatibility still produces problems on some + platforms, True64 and SGI IRIX begin two of them, so for now the + define is switched off. */ +#if 0 +#ifndef _XOPEN_SOURCE +# define _XOPEN_SOURCE 500 +#endif +#endif + +/* Include nearly all Python header files */ + +#include "patchlevel.h" +#include "pyconfig.h" + +#ifdef HAVE_LIMITS_H +#include <limits.h> +#endif + +/* pyconfig.h may or may not define DL_IMPORT */ +#ifndef DL_IMPORT /* declarations for DLL import/export */ +#define DL_IMPORT(RTYPE) RTYPE +#endif +#ifndef DL_EXPORT /* declarations for DLL import/export */ +#define DL_EXPORT(RTYPE) RTYPE +#endif + +#if defined(__sgi) && defined(WITH_THREAD) && !defined(_SGI_MP_SOURCE) +#define _SGI_MP_SOURCE +#endif + +#include <stdio.h> +#ifndef NULL +# error "Python.h requires that stdio.h define NULL." +#endif + +#include <string.h> +#include <errno.h> +#ifdef HAVE_STDLIB_H +#include <stdlib.h> +#endif +#if PY_MICRO_VERSION == 1 // Boost.Python modification: emulate Python 2.2 +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif +#endif // Boost.Python modification: emulate Python 2.2 + +/* CAUTION: Build setups should ensure that NDEBUG is defined on the + * compiler command line when building Python in release mode; else + * assert() calls won't be removed. + */ +#include <assert.h> + +#include "pyport.h" + +#include "pymem.h" + +#include "object.h" +#include "objimpl.h" + +#include "pydebug.h" + +#include "unicodeobject.h" +#include "intobject.h" +#include "longobject.h" +#include "floatobject.h" +#ifndef WITHOUT_COMPLEX +#include "complexobject.h" +#endif +#include "rangeobject.h" +#include "stringobject.h" +#include "bufferobject.h" +#include "tupleobject.h" +#include "listobject.h" +#include "dictobject.h" +#include "methodobject.h" +#include "moduleobject.h" +#include "funcobject.h" +#include "classobject.h" +#include "fileobject.h" +#include "cobject.h" +#include "traceback.h" +#include "sliceobject.h" +#include "cellobject.h" +extern "C" { // Boost.Python modification: provide missing extern "C" +#include "iterobject.h" +#include "descrobject.h" +} // Boost.Python modification: provide missing extern "C" +#include "weakrefobject.h" + +#include "codecs.h" +#include "pyerrors.h" + +#include "pystate.h" + +#include "modsupport.h" +#include "pythonrun.h" +#include "ceval.h" +#include "sysmodule.h" +#include "intrcheck.h" +#include "import.h" + +#include "abstract.h" + +#define PyArg_GetInt(v, a) PyArg_Parse((v), "i", (a)) +#define PyArg_NoArgs(v) PyArg_Parse(v, "") + +/* Convert a possibly signed character to a nonnegative int */ +/* XXX This assumes characters are 8 bits wide */ +#ifdef __CHAR_UNSIGNED__ +#define Py_CHARMASK(c) (c) +#else +#define Py_CHARMASK(c) ((c) & 0xff) +#endif + +#include "pyfpe.h" + +/* These definitions must match corresponding definitions in graminit.h. + There's code in compile.c that checks that they are the same. */ +#define Py_single_input 256 +#define Py_file_input 257 +#define Py_eval_input 258 + +#ifdef HAVE_PTH +/* GNU pth user-space thread support */ +#include <pth.h> +#endif +#endif /* !Py_PYTHON_H */ diff --git a/boost/python/detail/python_type.hpp b/boost/python/detail/python_type.hpp new file mode 100644 index 0000000000..f7630c175a --- /dev/null +++ b/boost/python/detail/python_type.hpp @@ -0,0 +1,37 @@ +// Copyright Nikolay Mladenov 2007. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef BOOST_PYTHON_OBJECT_PYTHON_TYPE_H +#define BOOST_PYTHON_OBJECT_PYTHON_TYPE_H + +#include <boost/python/converter/registered.hpp> + +namespace boost {namespace python {namespace detail{ + + +template <class T> struct python_class : PyObject +{ + typedef python_class<T> this_type; + + typedef T type; + + static void *converter (PyObject *p){ + return p; + } + + static void register_() + { + static bool first_time = true; + + if ( !first_time ) return; + + first_time = false; + converter::registry::insert(&converter, boost::python::type_id<this_type>(), &converter::registered_pytype_direct<T>::get_pytype); + } +}; + + +}}} //namespace boost :: python :: detail + +#endif //BOOST_PYTHON_OBJECT_PYTHON_TYPE_H diff --git a/boost/python/detail/raw_pyobject.hpp b/boost/python/detail/raw_pyobject.hpp new file mode 100644 index 0000000000..194409eda4 --- /dev/null +++ b/boost/python/detail/raw_pyobject.hpp @@ -0,0 +1,32 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef RAW_PYOBJECT_DWA2002628_HPP +# define RAW_PYOBJECT_DWA2002628_HPP + +namespace boost { namespace python { namespace detail { + +// +// Define some types which we can use to get around the vagaries of +// PyObject*. We will use these to initialize object instances, and +// keep them in namespace detail to make sure they stay out of the +// hands of users. That is much simpler than trying to grant +// friendship to all the appropriate parties. +// + +// New references are normally checked for null +struct new_reference_t; +typedef new_reference_t* new_reference; + +// Borrowed references are assumed to be non-null +struct borrowed_reference_t; +typedef borrowed_reference_t* borrowed_reference; + +// New references which aren't checked for null +struct new_non_null_reference_t; +typedef new_non_null_reference_t* new_non_null_reference; + +}}} // namespace boost::python::detail + +#endif // RAW_PYOBJECT_DWA2002628_HPP diff --git a/boost/python/detail/referent_storage.hpp b/boost/python/detail/referent_storage.hpp new file mode 100644 index 0000000000..0a1ef5a04e --- /dev/null +++ b/boost/python/detail/referent_storage.hpp @@ -0,0 +1,76 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef REFERENT_STORAGE_DWA200278_HPP +# define REFERENT_STORAGE_DWA200278_HPP +# include <boost/mpl/if.hpp> +# include <cstddef> + +namespace boost { namespace python { namespace detail { + +struct alignment_dummy; +typedef void (*function_ptr)(); +typedef int (alignment_dummy::*member_ptr); +typedef int (alignment_dummy::*member_function_ptr)(); + +# define BOOST_PYTHON_ALIGNER(T, n) \ + typename mpl::if_c< \ + sizeof(T) <= size, T, char>::type t##n + +// Storage for size bytes, aligned to all fundamental types no larger than size +template <std::size_t size> +union aligned_storage +{ + BOOST_PYTHON_ALIGNER(char, 0); + BOOST_PYTHON_ALIGNER(short, 1); + BOOST_PYTHON_ALIGNER(int, 2); + BOOST_PYTHON_ALIGNER(long, 3); + BOOST_PYTHON_ALIGNER(float, 4); + BOOST_PYTHON_ALIGNER(double, 5); + BOOST_PYTHON_ALIGNER(long double, 6); + BOOST_PYTHON_ALIGNER(void*, 7); + BOOST_PYTHON_ALIGNER(function_ptr, 8); + BOOST_PYTHON_ALIGNER(member_ptr, 9); + BOOST_PYTHON_ALIGNER(member_function_ptr, 10); + char bytes[size]; +}; + +# undef BOOST_PYTHON_ALIGNER + + // Compute the size of T's referent. We wouldn't need this at all, + // but sizeof() is broken in CodeWarriors <= 8.0 + template <class T> struct referent_size; + +# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + + template <class T> + struct referent_size<T&> + { + BOOST_STATIC_CONSTANT( + std::size_t, value = sizeof(T)); + }; + +# else + + template <class T> struct referent_size + { + static T f(); + BOOST_STATIC_CONSTANT(std::size_t, value = sizeof(f())); + }; + +# endif + +// A metafunction returning a POD type which can store U, where T == +// U&. If T is not a reference type, returns a POD which can store T. +template <class T> +struct referent_storage +{ + typedef aligned_storage< + ::boost::python::detail::referent_size<T>::value + > type; +}; + +}}} // namespace boost::python::detail + +#endif // REFERENT_STORAGE_DWA200278_HPP diff --git a/boost/python/detail/result.hpp b/boost/python/detail/result.hpp new file mode 100644 index 0000000000..9b8b486423 --- /dev/null +++ b/boost/python/detail/result.hpp @@ -0,0 +1,135 @@ +#if !defined(BOOST_PP_IS_ITERATING) + +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +# ifndef RESULT_DWA2002521_HPP +# define RESULT_DWA2002521_HPP + +# include <boost/type.hpp> + +# include <boost/python/detail/preprocessor.hpp> + +# include <boost/type_traits/object_traits.hpp> +# include <boost/mpl/if.hpp> + +# include <boost/preprocessor/comma_if.hpp> +# include <boost/preprocessor/iterate.hpp> +# include <boost/preprocessor/debug/line.hpp> +# include <boost/preprocessor/enum_params.hpp> +# include <boost/preprocessor/repetition/enum_trailing_params.hpp> + +namespace boost { namespace python { namespace detail { + +// Defines a family of overloaded function which, given x, a function +// pointer, member [function] pointer, or an AdaptableFunction object, +// returns a pointer to type<R>*, where R is the result type of +// invoking the result of bind(x). +// +// In order to work around bugs in deficient compilers, if x might be +// an AdaptableFunction object, you must pass OL as a second argument +// to get this to work portably. + +# define BOOST_PP_ITERATION_PARAMS_1 \ + (4, (0, BOOST_PYTHON_MAX_ARITY, <boost/python/detail/result.hpp>, BOOST_PYTHON_FUNCTION_POINTER)) +# include BOOST_PP_ITERATE() + +# define BOOST_PP_ITERATION_PARAMS_1 \ + (4, (0, BOOST_PYTHON_CV_COUNT - 1, <boost/python/detail/result.hpp>, BOOST_PYTHON_POINTER_TO_MEMBER)) +# include BOOST_PP_ITERATE() + +template <class R, class T> +boost::type<R>* result(R (T::*), int = 0) { return 0; } + +# if (defined(BOOST_MSVC) && _MSC_FULL_VER <= 13102140) \ + || (defined(__GNUC__) && __GNUC__ < 3) \ + || (defined(__MWERKS__) && __MWERKS__ < 0x3000) +// This code actually works on all implementations, but why use it when we don't have to? +template <class T> +struct get_result_type +{ + typedef boost::type<typename T::result_type> type; +}; + +struct void_type +{ + typedef void type; +}; + +template <class T> +struct result_result +{ + typedef typename mpl::if_c< + is_class<T>::value + , get_result_type<T> + , void_type + >::type t1; + + typedef typename t1::type* type; +}; + +template <class X> +typename result_result<X>::type +result(X const&, short) { return 0; } + +# else // Simpler code for more-capable compilers +template <class X> +boost::type<typename X::result_type>* +result(X const&, short = 0) { return 0; } + +# endif + +}}} // namespace boost::python::detail + +# endif // RESULT_DWA2002521_HPP + +/* --------------- function pointers --------------- */ +// For gcc 4.4 compatability, we must include the +// BOOST_PP_ITERATION_DEPTH test inside an #else clause. +#else // BOOST_PP_IS_ITERATING +#if BOOST_PP_ITERATION_DEPTH() == 1 && BOOST_PP_ITERATION_FLAGS() == BOOST_PYTHON_FUNCTION_POINTER +# if !(BOOST_WORKAROUND(__MWERKS__, > 0x3100) \ + && BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3201))) +# line BOOST_PP_LINE(__LINE__, result.hpp(function pointers)) +# endif + +# define N BOOST_PP_ITERATION() + +template <class R BOOST_PP_ENUM_TRAILING_PARAMS_Z(1, N, class A)> +boost::type<R>* result(R (*)(BOOST_PP_ENUM_PARAMS_Z(1, N, A)), int = 0) +{ + return 0; +} + +# undef N + +/* --------------- pointers-to-members --------------- */ +#elif BOOST_PP_ITERATION_DEPTH() == 1 && BOOST_PP_ITERATION_FLAGS() == BOOST_PYTHON_POINTER_TO_MEMBER +// Outer over cv-qualifiers + +# define BOOST_PP_ITERATION_PARAMS_2 (3, (0, BOOST_PYTHON_MAX_ARITY, <boost/python/detail/result.hpp>)) +# include BOOST_PP_ITERATE() + +#elif BOOST_PP_ITERATION_DEPTH() == 2 +# if !(BOOST_WORKAROUND(__MWERKS__, > 0x3100) \ + && BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3201))) +# line BOOST_PP_LINE(__LINE__, result.hpp(pointers-to-members)) +# endif +// Inner over arities + +# define N BOOST_PP_ITERATION() +# define Q BOOST_PYTHON_CV_QUALIFIER(BOOST_PP_RELATIVE_ITERATION(1)) + +template <class R, class T BOOST_PP_ENUM_TRAILING_PARAMS_Z(1, N, class A)> +boost::type<R>* result(R (T::*)(BOOST_PP_ENUM_PARAMS_Z(1, N, A)) Q, int = 0) +{ + return 0; +} + +# undef N +# undef Q + +#endif // BOOST_PP_ITERATION_DEPTH() +#endif diff --git a/boost/python/detail/scope.hpp b/boost/python/detail/scope.hpp new file mode 100644 index 0000000000..5367bbd35c --- /dev/null +++ b/boost/python/detail/scope.hpp @@ -0,0 +1,16 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef SCOPE_DWA2002927_HPP +# define SCOPE_DWA2002927_HPP + +# include <boost/python/detail/config.hpp> + +namespace boost { namespace python { namespace detail { + +void BOOST_PYTHON_DECL scope_setattr_doc(char const* name, object const& obj, char const* doc); + +}}} // namespace boost::python::detail + +#endif // SCOPE_DWA2002927_HPP diff --git a/boost/python/detail/sfinae.hpp b/boost/python/detail/sfinae.hpp new file mode 100644 index 0000000000..6281875111 --- /dev/null +++ b/boost/python/detail/sfinae.hpp @@ -0,0 +1,13 @@ +// Copyright David Abrahams 2004. Distributed under the Boost +// Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +#ifndef SFINAE_DWA2004723_HPP +# define SFINAE_DWA2004723_HPP + +# include <boost/python/detail/prefix.hpp> + +# if defined(BOOST_NO_SFINAE) && !defined(BOOST_MSVC) +# define BOOST_PYTHON_NO_SFINAE +# endif + +#endif // SFINAE_DWA2004723_HPP diff --git a/boost/python/detail/signature.hpp b/boost/python/detail/signature.hpp new file mode 100644 index 0000000000..11268b92cf --- /dev/null +++ b/boost/python/detail/signature.hpp @@ -0,0 +1,106 @@ +#if !defined(BOOST_PP_IS_ITERATING) + +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +# ifndef SIGNATURE_DWA20021121_HPP +# define SIGNATURE_DWA20021121_HPP + +# include <boost/python/type_id.hpp> + +# include <boost/python/detail/preprocessor.hpp> +# include <boost/python/detail/indirect_traits.hpp> +# include <boost/python/converter/pytype_function.hpp> + +# include <boost/preprocessor/iterate.hpp> +# include <boost/preprocessor/iteration/local.hpp> + +# include <boost/mpl/at.hpp> +# include <boost/mpl/size.hpp> + +namespace boost { namespace python { namespace detail { + +struct signature_element +{ + char const* basename; + converter::pytype_function pytype_f; + bool lvalue; +}; + +struct py_func_sig_info +{ + signature_element const *signature; + signature_element const *ret; +}; + +template <unsigned> struct signature_arity; + +# define BOOST_PP_ITERATION_PARAMS_1 \ + (3, (0, BOOST_PYTHON_MAX_ARITY + 1, <boost/python/detail/signature.hpp>)) +# include BOOST_PP_ITERATE() + +// A metafunction returning the base class used for +// +// signature<class F, class CallPolicies, class Sig>. +// +template <class Sig> +struct signature_base_select +{ + enum { arity = mpl::size<Sig>::value - 1 }; + typedef typename signature_arity<arity>::template impl<Sig> type; +}; + +template <class Sig> +struct signature + : signature_base_select<Sig>::type +{ +}; + +}}} // namespace boost::python::detail + +# endif // SIGNATURE_DWA20021121_HPP + +#else + +# define N BOOST_PP_ITERATION() + +template <> +struct signature_arity<N> +{ + template <class Sig> + struct impl + { + static signature_element const* elements() + { + static signature_element const result[N+2] = { + +#ifndef BOOST_PYTHON_NO_PY_SIGNATURES +# define BOOST_PP_LOCAL_MACRO(i) \ + { \ + type_id<BOOST_DEDUCED_TYPENAME mpl::at_c<Sig,i>::type>().name() \ + , &converter::expected_pytype_for_arg<BOOST_DEDUCED_TYPENAME mpl::at_c<Sig,i>::type>::get_pytype \ + , indirect_traits::is_reference_to_non_const<BOOST_DEDUCED_TYPENAME mpl::at_c<Sig,i>::type>::value \ + }, +#else +# define BOOST_PP_LOCAL_MACRO(i) \ + { \ + type_id<BOOST_DEDUCED_TYPENAME mpl::at_c<Sig,i>::type>().name() \ + , 0 \ + , indirect_traits::is_reference_to_non_const<BOOST_DEDUCED_TYPENAME mpl::at_c<Sig,i>::type>::value \ + }, +#endif + +# define BOOST_PP_LOCAL_LIMITS (0, N) +# include BOOST_PP_LOCAL_ITERATE() + {0,0,0} + }; + return result; + } + }; +}; + +#endif // BOOST_PP_IS_ITERATING + + diff --git a/boost/python/detail/string_literal.hpp b/boost/python/detail/string_literal.hpp new file mode 100644 index 0000000000..50193b6436 --- /dev/null +++ b/boost/python/detail/string_literal.hpp @@ -0,0 +1,88 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef STRING_LITERAL_DWA2002629_HPP +# define STRING_LITERAL_DWA2002629_HPP + +# include <cstddef> +# include <boost/type.hpp> +# include <boost/type_traits/array_traits.hpp> +# include <boost/type_traits/same_traits.hpp> +# include <boost/mpl/bool.hpp> +# include <boost/detail/workaround.hpp> + +namespace boost { namespace python { namespace detail { + +# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +template <class T> +struct is_string_literal : mpl::false_ +{ +}; + +# if !defined(__MWERKS__) || __MWERKS__ > 0x2407 +template <std::size_t n> +struct is_string_literal<char const[n]> : mpl::true_ +{ +}; + +# if BOOST_WORKAROUND(__DECCXX_VER, BOOST_TESTED_AT(60590040)) \ + || (defined(__sgi) && defined(_COMPILER_VERSION) && _COMPILER_VERSION <= 730) +// This compiler mistakenly gets the type of string literals as char* +// instead of char[NN]. +template <> +struct is_string_literal<char* const> : mpl::true_ +{ +}; +# endif + +# else + +// CWPro7 has trouble with the array type deduction above +template <class T, std::size_t n> +struct is_string_literal<T[n]> + : is_same<T, char const> +{ +}; +# endif +# else +template <bool is_array = true> +struct string_literal_helper +{ + typedef char (&yes_string_literal)[1]; + typedef char (&no_string_literal)[2]; + + template <class T> + struct apply + { + typedef apply<T> self; + static T x; + static yes_string_literal check(char const*); + static no_string_literal check(char*); + static no_string_literal check(void const volatile*); + + BOOST_STATIC_CONSTANT( + bool, value = sizeof(self::check(x)) == sizeof(yes_string_literal)); + typedef mpl::bool_<value> type; + }; +}; + +template <> +struct string_literal_helper<false> +{ + template <class T> + struct apply : mpl::false_ + { + }; +}; + +template <class T> +struct is_string_literal + : string_literal_helper<is_array<T>::value>::apply<T> +{ +}; +# endif + +}}} // namespace boost::python::detail + +#endif // STRING_LITERAL_DWA2002629_HPP diff --git a/boost/python/detail/target.hpp b/boost/python/detail/target.hpp new file mode 100644 index 0000000000..137801bb2b --- /dev/null +++ b/boost/python/detail/target.hpp @@ -0,0 +1,86 @@ +#if !defined(BOOST_PP_IS_ITERATING) + +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +# ifndef TARGET_DWA2002521_HPP +# define TARGET_DWA2002521_HPP + +# include <boost/python/detail/preprocessor.hpp> + +# include <boost/type.hpp> + +# include <boost/preprocessor/comma_if.hpp> +# include <boost/preprocessor/if.hpp> +# include <boost/preprocessor/iterate.hpp> +# include <boost/preprocessor/debug/line.hpp> +# include <boost/preprocessor/enum_params.hpp> +# include <boost/preprocessor/repetition/enum_trailing_params.hpp> + +namespace boost { namespace python { namespace detail { + +# define BOOST_PP_ITERATION_PARAMS_1 \ + (4, (0, BOOST_PYTHON_MAX_ARITY, <boost/python/detail/target.hpp>, BOOST_PYTHON_FUNCTION_POINTER)) +# include BOOST_PP_ITERATE() + +# define BOOST_PP_ITERATION_PARAMS_1 \ + (4, (0, BOOST_PYTHON_CV_COUNT - 1, <boost/python/detail/target.hpp>, BOOST_PYTHON_POINTER_TO_MEMBER)) +# include BOOST_PP_ITERATE() + +template <class R, class T> +T& (* target(R (T::*)) )() { return 0; } + +}}} // namespace boost::python::detail + +# endif // TARGET_DWA2002521_HPP + +/* --------------- function pointers --------------- */ +// For gcc 4.4 compatability, we must include the +// BOOST_PP_ITERATION_DEPTH test inside an #else clause. +#else // BOOST_PP_IS_ITERATING +#if BOOST_PP_ITERATION_DEPTH() == 1 && BOOST_PP_ITERATION_FLAGS() == BOOST_PYTHON_FUNCTION_POINTER +# if !(BOOST_WORKAROUND(__MWERKS__, > 0x3100) \ + && BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3201))) +# line BOOST_PP_LINE(__LINE__, target.hpp(function_pointers)) +# endif + +# define N BOOST_PP_ITERATION() + +template <class R BOOST_PP_ENUM_TRAILING_PARAMS_Z(1, N, class A)> +BOOST_PP_IF(N, A0, void)(* target(R (*)(BOOST_PP_ENUM_PARAMS_Z(1, N, A))) )() +{ + return 0; +} + +# undef N + +/* --------------- pointers-to-members --------------- */ +#elif BOOST_PP_ITERATION_DEPTH() == 1 && BOOST_PP_ITERATION_FLAGS() == BOOST_PYTHON_POINTER_TO_MEMBER +// Outer over cv-qualifiers + +# define BOOST_PP_ITERATION_PARAMS_2 (3, (0, BOOST_PYTHON_MAX_ARITY, <boost/python/detail/target.hpp>)) +# include BOOST_PP_ITERATE() + +#elif BOOST_PP_ITERATION_DEPTH() == 2 +# if !(BOOST_WORKAROUND(__MWERKS__, > 0x3100) \ + && BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3201))) +# line BOOST_PP_LINE(__LINE__, target.hpp(pointers-to-members)) +# endif +// Inner over arities + +# define N BOOST_PP_ITERATION() +# define Q BOOST_PYTHON_CV_QUALIFIER(BOOST_PP_RELATIVE_ITERATION(1)) + +template <class R, class T BOOST_PP_ENUM_TRAILING_PARAMS_Z(1, N, class A)> +T& (* target(R (T::*)(BOOST_PP_ENUM_PARAMS_Z(1, N, A)) Q) )() +{ + return 0; +} + +# undef N +# undef Q + +#endif // BOOST_PP_ITERATION_DEPTH() +#endif diff --git a/boost/python/detail/translate_exception.hpp b/boost/python/detail/translate_exception.hpp new file mode 100644 index 0000000000..df7ec2dd6c --- /dev/null +++ b/boost/python/detail/translate_exception.hpp @@ -0,0 +1,69 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef TRANSLATE_EXCEPTION_TDS20091020_HPP +# define TRANSLATE_EXCEPTION_TDS20091020_HPP + +# include <boost/python/detail/exception_handler.hpp> + +# include <boost/call_traits.hpp> +# include <boost/type_traits/add_const.hpp> +# include <boost/type_traits/add_reference.hpp> +# include <boost/type_traits/remove_reference.hpp> + +# include <boost/function/function0.hpp> + +namespace boost { namespace python { namespace detail { + +// A ternary function object used to translate C++ exceptions of type +// ExceptionType into Python exceptions by invoking an object of type +// Translate. Typically the translate function will be curried with +// boost::bind(). +template <class ExceptionType, class Translate> +struct translate_exception +{ +// workaround for broken gcc that ships with SuSE 9.0 and SuSE 9.1 +# if defined(__linux__) && defined(__GNUC__) \ + && BOOST_WORKAROUND(__GNUC__, == 3) \ + && BOOST_WORKAROUND(__GNUC_MINOR__, == 3) \ + && (BOOST_WORKAROUND(__GNUC_PATCHLEVEL__, == 1) \ + || BOOST_WORKAROUND(__GNUC_PATCHLEVEL__, == 3)) + typedef typename remove_reference< + typename add_const<ExceptionType>::type + >::type exception_non_ref; +# else + typedef typename add_reference< + typename add_const<ExceptionType>::type + >::type exception_cref; +# endif + + inline bool operator()( + exception_handler const& handler + , function0<void> const& f + , typename call_traits<Translate>::param_type translate) const + { + try + { + return handler(f); + } +// workaround for broken gcc that ships with SuSE 9.0 and SuSE 9.1 +# if defined(__linux__) && defined(__GNUC__) \ + && BOOST_WORKAROUND(__GNUC__, == 3) \ + && BOOST_WORKAROUND(__GNUC_MINOR__, == 3) \ + && (BOOST_WORKAROUND(__GNUC_PATCHLEVEL__, == 1) \ + || BOOST_WORKAROUND(__GNUC_PATCHLEVEL__, == 3)) + catch(exception_non_ref& e) +# else + catch(exception_cref e) +# endif + { + translate(e); + return true; + } + } +}; + +}}} // namespace boost::python::detail + +#endif // TRANSLATE_EXCEPTION_DWA2002810_HPP diff --git a/boost/python/detail/type_list.hpp b/boost/python/detail/type_list.hpp new file mode 100644 index 0000000000..9483c1945c --- /dev/null +++ b/boost/python/detail/type_list.hpp @@ -0,0 +1,39 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef TYPE_LIST_DWA2002913_HPP +# define TYPE_LIST_DWA2002913_HPP + +# include <boost/config.hpp> +# include <boost/python/detail/preprocessor.hpp> +# include <boost/preprocessor/arithmetic/inc.hpp> + +# if BOOST_PYTHON_MAX_ARITY + 2 > BOOST_PYTHON_MAX_BASES +# define BOOST_PYTHON_LIST_SIZE BOOST_PP_INC(BOOST_PP_INC(BOOST_PYTHON_MAX_ARITY)) +# else +# define BOOST_PYTHON_LIST_SIZE BOOST_PYTHON_MAX_BASES +# endif + +// Compute the MPL vector header to use for lists up to BOOST_PYTHON_LIST_SIZE in length +# if BOOST_PYTHON_LIST_SIZE > 48 +# error Arities above 48 not supported by Boost.Python due to MPL internal limit +# elif BOOST_PYTHON_LIST_SIZE > 38 +# include <boost/mpl/vector/vector50.hpp> +# elif BOOST_PYTHON_LIST_SIZE > 28 +# include <boost/mpl/vector/vector40.hpp> +# elif BOOST_PYTHON_LIST_SIZE > 18 +# include <boost/mpl/vector/vector30.hpp> +# elif BOOST_PYTHON_LIST_SIZE > 8 +# include <boost/mpl/vector/vector20.hpp> +# else +# include <boost/mpl/vector/vector10.hpp> +# endif + +# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +# include <boost/python/detail/type_list_impl.hpp> +# else +# include <boost/python/detail/type_list_impl_no_pts.hpp> +# endif + +#endif // TYPE_LIST_DWA2002913_HPP diff --git a/boost/python/detail/type_list_impl.hpp b/boost/python/detail/type_list_impl.hpp new file mode 100644 index 0000000000..fdcfa85030 --- /dev/null +++ b/boost/python/detail/type_list_impl.hpp @@ -0,0 +1,57 @@ +#ifndef BOOST_PP_IS_ITERATING +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +# ifndef TYPE_LIST_IMPL_DWA2002913_HPP +# define TYPE_LIST_IMPL_DWA2002913_HPP + +# include <boost/python/detail/type_list.hpp> + +# include <boost/preprocessor/enum_params.hpp> +# include <boost/preprocessor/enum_params_with_a_default.hpp> +# include <boost/preprocessor/repetition/enum.hpp> +# include <boost/preprocessor/comma_if.hpp> +# include <boost/preprocessor/arithmetic/sub.hpp> +# include <boost/preprocessor/iterate.hpp> +# include <boost/preprocessor/repetition/enum_trailing.hpp> + +namespace boost { namespace python { namespace detail { + +template <BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT(BOOST_PYTHON_LIST_SIZE, class T, mpl::void_)> +struct type_list + : BOOST_PP_CAT(mpl::vector,BOOST_PYTHON_LIST_SIZE)<BOOST_PP_ENUM_PARAMS_Z(1, BOOST_PYTHON_LIST_SIZE, T)> +{ +}; + +# define BOOST_PP_ITERATION_PARAMS_1 \ + (3, (0, BOOST_PP_DEC(BOOST_PYTHON_LIST_SIZE), <boost/python/detail/type_list_impl.hpp>)) +# include BOOST_PP_ITERATE() + + +}}} // namespace boost::python::detail + +# endif // TYPE_LIST_IMPL_DWA2002913_HPP + +#else // BOOST_PP_IS_ITERATING + +# define N BOOST_PP_ITERATION() +# define BOOST_PYTHON_VOID_ARGS BOOST_PP_SUB_D(1,BOOST_PYTHON_LIST_SIZE,N) + +template < + BOOST_PP_ENUM_PARAMS_Z(1, N, class T) + > +struct type_list< + BOOST_PP_ENUM_PARAMS_Z(1, N, T) + BOOST_PP_COMMA_IF(N) + BOOST_PP_ENUM( + BOOST_PYTHON_VOID_ARGS, BOOST_PYTHON_FIXED, mpl::void_) + > + : BOOST_PP_CAT(mpl::vector,N)<BOOST_PP_ENUM_PARAMS_Z(1, N, T)> +{ +}; + +# undef BOOST_PYTHON_VOID_ARGS +# undef N + +#endif // BOOST_PP_IS_ITERATING diff --git a/boost/python/detail/type_list_impl_no_pts.hpp b/boost/python/detail/type_list_impl_no_pts.hpp new file mode 100644 index 0000000000..15d9252374 --- /dev/null +++ b/boost/python/detail/type_list_impl_no_pts.hpp @@ -0,0 +1,107 @@ +#ifndef BOOST_PP_IS_ITERATING +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +# ifndef TYPE_LIST_IMPL_NO_PTS_DWA2002913_HPP +# define TYPE_LIST_IMPL_NO_PTS_DWA2002913_HPP + +# include <boost/python/detail/type_list.hpp> + +# include <boost/preprocessor/enum_params.hpp> +# include <boost/preprocessor/enum_params_with_a_default.hpp> +# include <boost/preprocessor/cat.hpp> +# include <boost/preprocessor/repeat.hpp> +# include <boost/preprocessor/empty.hpp> +# include <boost/preprocessor/iterate.hpp> +# include <boost/mpl/void.hpp> + +namespace boost { namespace python { namespace detail { + +template< typename T > +struct is_list_arg +{ + enum { value = true }; +}; + +template<> +struct is_list_arg<mpl::void_> +{ + enum { value = false }; +}; + +template<int> struct type_list_impl_chooser; + +# define BOOST_PYTHON_LIST_ACTUAL_PARAMS BOOST_PP_ENUM_PARAMS_Z(1,BOOST_PYTHON_LIST_SIZE,T) +# define BOOST_PYTHON_LIST_FORMAL_PARAMS BOOST_PP_ENUM_PARAMS_Z(1,BOOST_PYTHON_LIST_SIZE,class T) + +# define BOOST_PP_ITERATION_PARAMS_1 \ + (3, (0, BOOST_PYTHON_LIST_SIZE, <boost/python/detail/type_list_impl_no_pts.hpp>)) +# include BOOST_PP_ITERATE() + +# define BOOST_PYTHON_PLUS() + +# define BOOST_PYTHON_IS_LIST_ARG(z, n, data) \ + BOOST_PP_IF(n, BOOST_PYTHON_PLUS, BOOST_PP_EMPTY)() \ + is_list_arg< BOOST_PP_CAT(T,n) >::value + +template< + BOOST_PYTHON_LIST_FORMAL_PARAMS + > +struct type_list_count_args +{ + enum { value = + BOOST_PP_REPEAT_1(BOOST_PYTHON_LIST_SIZE, BOOST_PYTHON_IS_LIST_ARG, _) + }; +}; + +template< + BOOST_PYTHON_LIST_FORMAL_PARAMS + > +struct type_list_impl +{ + typedef type_list_count_args< BOOST_PYTHON_LIST_ACTUAL_PARAMS > arg_num_; + typedef typename detail::type_list_impl_chooser< arg_num_::value > + ::template result_< BOOST_PYTHON_LIST_ACTUAL_PARAMS >::type type; +}; + +template< + BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT(BOOST_PYTHON_LIST_SIZE, class T, mpl::void_) + > +struct type_list + : detail::type_list_impl< BOOST_PYTHON_LIST_ACTUAL_PARAMS >::type +{ + typedef typename detail::type_list_impl< + BOOST_PYTHON_LIST_ACTUAL_PARAMS + >::type type; +}; + +# undef BOOST_PYTHON_IS_LIST_ARG +# undef BOOST_PYTHON_PLUS +# undef BOOST_PYTHON_LIST_FORMAL_PARAMS +# undef BOOST_PYTHON_LIST_ACTUAL_PARAMS + +}}} // namespace boost::python::detail + +# endif // TYPE_LIST_IMPL_NO_PTS_DWA2002913_HPP + +#else // BOOST_PP_IS_ITERATING + +# define N BOOST_PP_ITERATION() + +template<> +struct type_list_impl_chooser<N> +{ + template< + BOOST_PYTHON_LIST_FORMAL_PARAMS + > + struct result_ + { + typedef typename BOOST_PP_CAT(mpl::vector,N)< + BOOST_PP_ENUM_PARAMS(N, T) + >::type type; + }; +}; + +# undef N + +#endif // BOOST_PP_IS_ITERATING diff --git a/boost/python/detail/unwind_type.hpp b/boost/python/detail/unwind_type.hpp new file mode 100644 index 0000000000..9a997c9dbd --- /dev/null +++ b/boost/python/detail/unwind_type.hpp @@ -0,0 +1,170 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef UNWIND_TYPE_DWA200222_HPP +# define UNWIND_TYPE_DWA200222_HPP + +# include <boost/python/detail/cv_category.hpp> +# include <boost/python/detail/indirect_traits.hpp> +# include <boost/type_traits/object_traits.hpp> + +namespace boost { namespace python { namespace detail { + +#ifndef _MSC_VER //if forward declared, msvc6.5 does not recognize them as inline +// forward declaration, required (at least) by Tru64 cxx V6.5-042 +template <class Generator, class U> +inline typename Generator::result_type +unwind_type(U const& p, Generator* = 0); + +// forward declaration, required (at least) by Tru64 cxx V6.5-042 +template <class Generator, class U> +inline typename Generator::result_type +unwind_type(boost::type<U>*p = 0, Generator* = 0); +#endif + +template <class Generator, class U> +inline typename Generator::result_type +unwind_type_cv(U* p, cv_unqualified, Generator* = 0) +{ + return Generator::execute(p); +} + +template <class Generator, class U> +inline typename Generator::result_type +unwind_type_cv(U const* p, const_, Generator* = 0) +{ + return unwind_type(const_cast<U*>(p), (Generator*)0); +} + +template <class Generator, class U> +inline typename Generator::result_type +unwind_type_cv(U volatile* p, volatile_, Generator* = 0) +{ + return unwind_type(const_cast<U*>(p), (Generator*)0); +} + +template <class Generator, class U> +inline typename Generator::result_type +unwind_type_cv(U const volatile* p, const_volatile_, Generator* = 0) +{ + return unwind_type(const_cast<U*>(p), (Generator*)0); +} + +template <class Generator, class U> +inline typename Generator::result_type +unwind_ptr_type(U* p, Generator* = 0) +{ + typedef typename cv_category<U>::type tag; + return unwind_type_cv<Generator>(p, tag()); +} + +template <bool is_ptr> +struct unwind_helper +{ + template <class Generator, class U> + static typename Generator::result_type + execute(U p, Generator* = 0) + { + return unwind_ptr_type(p, (Generator*)0); + } +}; + +template <> +struct unwind_helper<false> +{ + template <class Generator, class U> + static typename Generator::result_type + execute(U& p, Generator* = 0) + { + return unwind_ptr_type(&p, (Generator*)0); + } +}; + +template <class Generator, class U> +inline typename Generator::result_type +#ifndef _MSC_VER +unwind_type(U const& p, Generator*) +#else +unwind_type(U const& p, Generator* = 0) +#endif +{ + return unwind_helper<is_pointer<U>::value>::execute(p, (Generator*)0); +} + +enum { direct_ = 0, pointer_ = 1, reference_ = 2, reference_to_pointer_ = 3 }; +template <int indirection> struct unwind_helper2; + +template <> +struct unwind_helper2<direct_> +{ + template <class Generator, class U> + static typename Generator::result_type + execute(U(*)(), Generator* = 0) + { + return unwind_ptr_type((U*)0, (Generator*)0); + } +}; + +template <> +struct unwind_helper2<pointer_> +{ + template <class Generator, class U> + static typename Generator::result_type + execute(U*(*)(), Generator* = 0) + { + return unwind_ptr_type((U*)0, (Generator*)0); + } +}; + +template <> +struct unwind_helper2<reference_> +{ + template <class Generator, class U> + static typename Generator::result_type + execute(U&(*)(), Generator* = 0) + { + return unwind_ptr_type((U*)0, (Generator*)0); + } +}; + +template <> +struct unwind_helper2<reference_to_pointer_> +{ + template <class Generator, class U> + static typename Generator::result_type + execute(U&(*)(), Generator* = 0) + { + return unwind_ptr_type(U(0), (Generator*)0); + } +}; + +// Call this one with both template parameters explicitly specified +// and no function arguments: +// +// return unwind_type<my_generator,T>(); +// +// Doesn't work if T is an array type; we could handle that case, but +// why bother? +template <class Generator, class U> +inline typename Generator::result_type +#ifndef _MSC_VER +unwind_type(boost::type<U>*, Generator*) +#else +unwind_type(boost::type<U>*p =0, Generator* =0) +#endif +{ + BOOST_STATIC_CONSTANT(int, indirection + = (boost::is_pointer<U>::value ? pointer_ : 0) + + (indirect_traits::is_reference_to_pointer<U>::value + ? reference_to_pointer_ + : boost::is_reference<U>::value + ? reference_ + : 0)); + + return unwind_helper2<indirection>::execute((U(*)())0,(Generator*)0); +} + +}}} // namespace boost::python::detail + +#endif // UNWIND_TYPE_DWA200222_HPP diff --git a/boost/python/detail/unwrap_type_id.hpp b/boost/python/detail/unwrap_type_id.hpp new file mode 100644 index 0000000000..96c1f53013 --- /dev/null +++ b/boost/python/detail/unwrap_type_id.hpp @@ -0,0 +1,31 @@ +// Copyright David Abrahams 2004. Distributed under the Boost +// Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +#ifndef UNWRAP_TYPE_ID_DWA2004722_HPP +# define UNWRAP_TYPE_ID_DWA2004722_HPP + +# include <boost/python/type_id.hpp> + +# include <boost/mpl/bool.hpp> + +namespace boost { namespace python { + +template <class T> class wrapper; + +namespace detail { + +template <class T> +inline type_info unwrap_type_id(T*, ...) +{ + return type_id<T>(); +} + +template <class U, class T> +inline type_info unwrap_type_id(U*, wrapper<T>*) +{ + return type_id<T>(); +} + +}}} // namespace boost::python::detail + +#endif // UNWRAP_TYPE_ID_DWA2004722_HPP diff --git a/boost/python/detail/unwrap_wrapper.hpp b/boost/python/detail/unwrap_wrapper.hpp new file mode 100644 index 0000000000..95bc233a72 --- /dev/null +++ b/boost/python/detail/unwrap_wrapper.hpp @@ -0,0 +1,34 @@ +// Copyright David Abrahams 2004. Distributed under the Boost +// Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +#ifndef UNWRAP_WRAPPER_DWA2004723_HPP +# define UNWRAP_WRAPPER_DWA2004723_HPP + +# include <boost/python/detail/prefix.hpp> +# include <boost/python/detail/is_wrapper.hpp> +# include <boost/mpl/eval_if.hpp> +# include <boost/mpl/identity.hpp> + +namespace boost { namespace python { namespace detail { + +template <class T> +struct unwrap_wrapper_helper +{ + typedef typename T::_wrapper_wrapped_type_ type; +}; + +template <class T> +struct unwrap_wrapper_ + : mpl::eval_if<is_wrapper<T>,unwrap_wrapper_helper<T>,mpl::identity<T> > +{}; + +template <class T> +typename unwrap_wrapper_<T>::type* +unwrap_wrapper(T*) +{ + return 0; +} + +}}} // namespace boost::python::detail + +#endif // UNWRAP_WRAPPER_DWA2004723_HPP diff --git a/boost/python/detail/value_arg.hpp b/boost/python/detail/value_arg.hpp new file mode 100644 index 0000000000..747588d6fd --- /dev/null +++ b/boost/python/detail/value_arg.hpp @@ -0,0 +1,27 @@ +// Copyright David Abrahams 2004. Distributed under the Boost +// Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +#ifndef VALUE_ARG_DWA2004312_HPP +# define VALUE_ARG_DWA2004312_HPP + +# include <boost/python/detail/copy_ctor_mutates_rhs.hpp> +# include <boost/mpl/if.hpp> +# include <boost/type_traits/add_reference.hpp> +# include <boost/type_traits/add_const.hpp> + +namespace boost { namespace python { namespace detail { + +template <class T> +struct value_arg + : mpl::if_< + copy_ctor_mutates_rhs<T> + , T + , typename add_reference< + typename add_const<T>::type + >::type + > +{}; + +}}} // namespace boost::python::detail + +#endif // VALUE_ARG_DWA2004312_HPP diff --git a/boost/python/detail/value_is_shared_ptr.hpp b/boost/python/detail/value_is_shared_ptr.hpp new file mode 100644 index 0000000000..361c369b5b --- /dev/null +++ b/boost/python/detail/value_is_shared_ptr.hpp @@ -0,0 +1,17 @@ +// Copyright David Abrahams 2003. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef VALUE_IS_SHARED_PTR_DWA2003224_HPP +# define VALUE_IS_SHARED_PTR_DWA2003224_HPP + +# include <boost/python/detail/value_is_xxx.hpp> +# include <boost/shared_ptr.hpp> + +namespace boost { namespace python { namespace detail { + +BOOST_PYTHON_VALUE_IS_XXX_DEF(shared_ptr, shared_ptr, 1) + +}}} // namespace boost::python::detail + +#endif // VALUE_IS_SHARED_PTR_DWA2003224_HPP diff --git a/boost/python/detail/value_is_xxx.hpp b/boost/python/detail/value_is_xxx.hpp new file mode 100644 index 0000000000..2b12564907 --- /dev/null +++ b/boost/python/detail/value_is_xxx.hpp @@ -0,0 +1,62 @@ +// Copyright David Abrahams 2003. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef VALUE_IS_XXX_DWA2003224_HPP +# define VALUE_IS_XXX_DWA2003224_HPP + +# include <boost/config.hpp> +# include <boost/mpl/bool.hpp> +# include <boost/preprocessor/enum_params.hpp> + +# if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) +# include <boost/type_traits/is_reference.hpp> +# include <boost/type_traits/add_reference.hpp> + +# define BOOST_PYTHON_VALUE_IS_XXX_DEF(name, qualified_name, nargs) \ +template <class X_> \ +struct value_is_##name \ +{ \ + typedef char yes; \ + typedef char (&no)[2]; \ + \ + static typename add_reference<X_>::type dummy; \ + \ + template < BOOST_PP_ENUM_PARAMS_Z(1, nargs, class U) > \ + static yes test( \ + qualified_name< BOOST_PP_ENUM_PARAMS_Z(1, nargs, U) > const&, int \ + ); \ + \ + template <class U> \ + static no test(U&, ...); \ + \ + BOOST_STATIC_CONSTANT( \ + bool, value \ + = (sizeof(test(dummy, 0)) == sizeof(yes))); \ + \ + typedef mpl::bool_<value> type; \ +}; + +# else + +# include <boost/type_traits/remove_reference.hpp> +# include <boost/type_traits/remove_cv.hpp> +# include <boost/python/detail/is_xxx.hpp> + +# define BOOST_PYTHON_VALUE_IS_XXX_DEF(name, qualified_name, nargs) \ +template <class X_> \ +struct value_is_##name \ +{ \ + BOOST_PYTHON_IS_XXX_DEF(name,qualified_name,nargs) \ + BOOST_STATIC_CONSTANT(bool, value = is_##name< \ + typename remove_cv< \ + typename remove_reference<X_>::type \ + >::type \ + >::value); \ + typedef mpl::bool_<value> type; \ + \ +}; + +# endif + +#endif // VALUE_IS_XXX_DWA2003224_HPP diff --git a/boost/python/detail/void_ptr.hpp b/boost/python/detail/void_ptr.hpp new file mode 100644 index 0000000000..06f680104d --- /dev/null +++ b/boost/python/detail/void_ptr.hpp @@ -0,0 +1,35 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef VOID_PTR_DWA200239_HPP +# define VOID_PTR_DWA200239_HPP + +# include <boost/type_traits/remove_cv.hpp> + +namespace boost { namespace python { namespace detail { + +template <class U> +inline U& void_ptr_to_reference(void const volatile* p, U&(*)()) +{ + return *(U*)p; +} + +template <class T> +inline void write_void_ptr(void const volatile* storage, void* ptr, T*) +{ + *(T**)storage = (T*)ptr; +} + +// writes U(ptr) into the storage +template <class U> +inline void write_void_ptr_reference(void const volatile* storage, void* ptr, U&(*)()) +{ + // stripping CV qualification suppresses warnings on older EDGs + typedef typename remove_cv<U>::type u_stripped; + write_void_ptr(storage, ptr, u_stripped(0)); +} + +}}} // namespace boost::python::detail + +#endif // VOID_PTR_DWA200239_HPP diff --git a/boost/python/detail/void_return.hpp b/boost/python/detail/void_return.hpp new file mode 100644 index 0000000000..30db825177 --- /dev/null +++ b/boost/python/detail/void_return.hpp @@ -0,0 +1,42 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef VOID_RETURN_DWA200274_HPP +# define VOID_RETURN_DWA200274_HPP + +# include <boost/config.hpp> + +namespace boost { namespace python { namespace detail { + +struct void_return +{ + void_return() {} + private: + void operator=(void_return const&); +}; + +template <class T> +struct returnable +{ + typedef T type; +}; + +# ifdef BOOST_NO_VOID_RETURNS +template <> +struct returnable<void> +{ + typedef void_return type; +}; + +# ifndef BOOST_NO_CV_VOID_SPECIALIZATIONS +template <> struct returnable<const void> : returnable<void> {}; +template <> struct returnable<volatile void> : returnable<void> {}; +template <> struct returnable<const volatile void> : returnable<void> {}; +# endif + +# endif // BOOST_NO_VOID_RETURNS + +}}} // namespace boost::python::detail + +#endif // VOID_RETURN_DWA200274_HPP diff --git a/boost/python/detail/wrap_python.hpp b/boost/python/detail/wrap_python.hpp new file mode 100644 index 0000000000..eaef7841d5 --- /dev/null +++ b/boost/python/detail/wrap_python.hpp @@ -0,0 +1,205 @@ +// (C) Copyright David Abrahams 2000. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// The author gratefully acknowleges the support of Dragon Systems, Inc., in +// producing this work. + +// This file serves as a wrapper around <Python.h> which allows it to be +// compiled with GCC 2.95.2 under Win32 and which disables the default MSVC +// behavior so that a program may be compiled in debug mode without requiring a +// special debugging build of the Python library. + + +// To use the Python debugging library, #define BOOST_DEBUG_PYTHON on the +// compiler command-line. + +// Revision History: +// 05 Mar 01 Suppress warnings under Cygwin with Python 2.0 (Dave Abrahams) +// 04 Mar 01 Rolled in some changes from the Dragon fork (Dave Abrahams) +// 01 Mar 01 define PyObject_INIT() for Python 1.x (Dave Abrahams) + +#ifdef _DEBUG +# ifndef BOOST_DEBUG_PYTHON +# ifdef _MSC_VER + // VC8.0 will complain if system headers are #included both with + // and without _DEBUG defined, so we have to #include all the + // system headers used by pyconfig.h right here. +# include <stddef.h> +# include <stdarg.h> +# include <stdio.h> +# include <stdlib.h> +# include <assert.h> +# include <errno.h> +# include <ctype.h> +# include <wchar.h> +# include <basetsd.h> +# include <io.h> +# include <limits.h> +# include <float.h> +# include <string.h> +# include <math.h> +# include <time.h> +# endif +# undef _DEBUG // Don't let Python force the debug library just because we're debugging. +# define DEBUG_UNDEFINED_FROM_WRAP_PYTHON_H +# endif +#endif + +# include <pyconfig.h> +# if defined(_SGI_COMPILER_VERSION) && _SGI_COMPILER_VERSION >= 740 +# undef _POSIX_C_SOURCE +# undef _XOPEN_SOURCE +# undef HAVE_STDINT_H // undo Python 2.5.1 define +# endif + +// +// Python's LongObject.h helpfully #defines ULONGLONG_MAX for us, +// which confuses Boost's config +// +#include <limits.h> +#ifndef ULONG_MAX +# define BOOST_PYTHON_ULONG_MAX_UNDEFINED +#endif +#ifndef LONGLONG_MAX +# define BOOST_PYTHON_LONGLONG_MAX_UNDEFINED +#endif +#ifndef ULONGLONG_MAX +# define BOOST_PYTHON_ULONGLONG_MAX_UNDEFINED +#endif + +// +// Get ahold of Python's version number +// +#include <patchlevel.h> + +#if PY_MAJOR_VERSION<2 || PY_MAJOR_VERSION==2 && PY_MINOR_VERSION<2 +#error Python 2.2 or higher is required for this version of Boost.Python. +#endif + +// +// Some things we need in order to get Python.h to work with compilers other +// than MSVC on Win32 +// +#if defined(_WIN32) || defined(__CYGWIN__) +# if defined(__GNUC__) && defined(__CYGWIN__) + +# define SIZEOF_LONG 4 + +# if PY_MAJOR_VERSION < 2 || PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION <= 2 + +typedef int pid_t; + +# define WORD_BIT 32 +# define hypot _hypot +# include <stdio.h> + +# if PY_MAJOR_VERSION < 2 +# define HAVE_CLOCK +# define HAVE_STRFTIME +# define HAVE_STRERROR +# endif + +# define NT_THREADS + +# ifndef NETSCAPE_PI +# define USE_SOCKET +# endif + +# ifdef USE_DL_IMPORT +# define DL_IMPORT(RTYPE) __declspec(dllimport) RTYPE +# endif + +# ifdef USE_DL_EXPORT +# define DL_IMPORT(RTYPE) __declspec(dllexport) RTYPE +# define DL_EXPORT(RTYPE) __declspec(dllexport) RTYPE +# endif + +# define HAVE_LONG_LONG 1 +# define LONG_LONG long long +# endif + +# elif defined(__MWERKS__) + +# ifndef _MSC_VER +# define PY_MSC_VER_DEFINED_FROM_WRAP_PYTHON_H 1 +# define _MSC_VER 900 +# endif + +# undef hypot // undo the evil #define left by Python. + +# elif defined(__BORLANDC__) +# undef HAVE_HYPOT +# define HAVE_HYPOT 1 +# endif + +#endif // _WIN32 + +#if PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION == 2 && PY_MICRO_VERSION < 2 +# include <boost/python/detail/python22_fixed.h> +#else +# include <Python.h> +#endif + +#ifdef BOOST_PYTHON_ULONG_MAX_UNDEFINED +# undef ULONG_MAX +# undef BOOST_PYTHON_ULONG_MAX_UNDEFINED +#endif + +#ifdef BOOST_PYTHON_LONGLONG_MAX_UNDEFINED +# undef LONGLONG_MAX +# undef BOOST_PYTHON_LONGLONG_MAX_UNDEFINED +#endif + +#ifdef BOOST_PYTHON_ULONGLONG_MAX_UNDEFINED +# undef ULONGLONG_MAX +# undef BOOST_PYTHON_ULONGLONG_MAX_UNDEFINED +#endif + +#ifdef PY_MSC_VER_DEFINED_FROM_WRAP_PYTHON_H +# undef _MSC_VER +#endif + +#ifdef DEBUG_UNDEFINED_FROM_WRAP_PYTHON_H +# undef DEBUG_UNDEFINED_FROM_WRAP_PYTHON_H +# define _DEBUG +# ifdef _CRT_NOFORCE_MANIFEST_DEFINED_FROM_WRAP_PYTHON_H +# undef _CRT_NOFORCE_MANIFEST_DEFINED_FROM_WRAP_PYTHON_H +# undef _CRT_NOFORCE_MANIFEST +# endif +#endif + +#if !defined(PY_MAJOR_VERSION) || PY_MAJOR_VERSION < 2 +# define PyObject_INIT(op, typeobj) \ + ( (op)->ob_type = (typeobj), _Py_NewReference((PyObject *)(op)), (op) ) +#endif + +// Define Python 3 macros for Python 2.x +#if PY_VERSION_HEX < 0x02060000 + +# define Py_TYPE(o) (((PyObject*)(o))->ob_type) +# define Py_REFCNT(o) (((PyObject*)(o))->ob_refcnt) +# define Py_SIZE(o) (((PyVarObject*)(o))->ob_size) + +# define PyVarObject_HEAD_INIT(type, size) \ + PyObject_HEAD_INIT(type) size, + +#endif + + +#ifdef __MWERKS__ +# pragma warn_possunwant off +#elif _MSC_VER +# pragma warning(disable:4786) +#endif + +#if defined(HAVE_LONG_LONG) +# if defined(PY_LONG_LONG) +# define BOOST_PYTHON_LONG_LONG PY_LONG_LONG +# elif defined(LONG_LONG) +# define BOOST_PYTHON_LONG_LONG LONG_LONG +# else +# error "HAVE_LONG_LONG defined but not PY_LONG_LONG or LONG_LONG" +# endif +#endif diff --git a/boost/python/detail/wrapper_base.hpp b/boost/python/detail/wrapper_base.hpp new file mode 100644 index 0000000000..e5b93aa449 --- /dev/null +++ b/boost/python/detail/wrapper_base.hpp @@ -0,0 +1,90 @@ +// Copyright David Abrahams 2004. Distributed under the Boost +// Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +#ifndef WRAPPER_BASE_DWA2004722_HPP +# define WRAPPER_BASE_DWA2004722_HPP + +# include <boost/python/detail/prefix.hpp> +# include <boost/type_traits/is_polymorphic.hpp> +# include <boost/mpl/bool.hpp> + +namespace boost { namespace python { + +class override; + +namespace detail +{ + class BOOST_PYTHON_DECL_FORWARD wrapper_base; + + namespace wrapper_base_ // ADL disabler + { + inline PyObject* get_owner(wrapper_base const volatile& w); + + inline PyObject* + owner_impl(void const volatile* /*x*/, mpl::false_) + { + return 0; + } + + template <class T> + inline PyObject* + owner_impl(T const volatile* x, mpl::true_); + + template <class T> + inline PyObject* + owner(T const volatile* x) + { + return wrapper_base_::owner_impl(x,is_polymorphic<T>()); + } + } + + class BOOST_PYTHON_DECL wrapper_base + { + friend void initialize_wrapper(PyObject* self, wrapper_base* w); + friend PyObject* wrapper_base_::get_owner(wrapper_base const volatile& w); + protected: + wrapper_base() : m_self(0) {} + + override get_override( + char const* name, PyTypeObject* class_object) const; + + private: + void detach(); + + private: + PyObject* m_self; + }; + + namespace wrapper_base_ // ADL disabler + { + template <class T> + inline PyObject* + owner_impl(T const volatile* x, mpl::true_) + { + if (wrapper_base const volatile* w = dynamic_cast<wrapper_base const volatile*>(x)) + { + return wrapper_base_::get_owner(*w); + } + return 0; + } + + inline PyObject* get_owner(wrapper_base const volatile& w) + { + return w.m_self; + } + } + + inline void initialize_wrapper(PyObject* self, wrapper_base* w) + { + w->m_self = self; + } + + inline void initialize_wrapper(PyObject* /*self*/, ...) {} + + + +} // namespace detail + +}} // namespace boost::python + +#endif // WRAPPER_BASE_DWA2004722_HPP diff --git a/boost/python/dict.hpp b/boost/python/dict.hpp new file mode 100644 index 0000000000..6fcaf14382 --- /dev/null +++ b/boost/python/dict.hpp @@ -0,0 +1,152 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef DICT_20020706_HPP +#define DICT_20020706_HPP + +# include <boost/python/detail/prefix.hpp> + +#include <boost/python/object.hpp> +#include <boost/python/list.hpp> +#include <boost/python/tuple.hpp> +#include <boost/python/converter/pytype_object_mgr_traits.hpp> + +namespace boost { namespace python { + +class dict; + +namespace detail +{ + struct BOOST_PYTHON_DECL dict_base : object + { + // D.clear() -> None. Remove all items from D. + void clear(); + + // D.copy() -> a shallow copy of D + dict copy(); + + // D.get(k[,d]) -> D[k] if D.has_key(k), else d. d defaults to None. + object get(object_cref k) const; + + object get(object_cref k, object_cref d) const; + + // D.has_key(k) -> 1 if D has a key k, else 0 + bool has_key(object_cref k) const; + + // D.items() -> list of D's (key, value) pairs, as 2-tuples + list items() const; + + // D.iteritems() -> an iterator over the (key, value) items of D + object iteritems() const; + + // D.iterkeys() -> an iterator over the keys of D + object iterkeys() const; + + // D.itervalues() -> an iterator over the values of D + object itervalues() const; + + // D.keys() -> list of D's keys + list keys() const; + + // D.popitem() -> (k, v), remove and return some (key, value) pair as a + // 2-tuple; but raise KeyError if D is empty + tuple popitem(); + + // D.setdefault(k[,d]) -> D.get(k,d), also set D[k]=d if not D.has_key(k) + object setdefault(object_cref k); + + object setdefault(object_cref k, object_cref d); + + // D.update(E) -> None. Update D from E: for k in E.keys(): D[k] = E[k] + void update(object_cref E); + + // D.values() -> list of D's values + list values() const; + + protected: + // dict() -> new empty dictionary. + // dict(mapping) -> new dictionary initialized from a mapping object's + // (key, value) pairs. + // dict(seq) -> new dictionary initialized as if via: + dict_base(); // new dict + explicit dict_base(object_cref data); + + BOOST_PYTHON_FORWARD_OBJECT_CONSTRUCTORS(dict_base, object) + private: + static detail::new_reference call(object const&); + }; +} + +class dict : public detail::dict_base +{ + typedef detail::dict_base base; + public: + // dict() -> new empty dictionary. + // dict(mapping) -> new dictionary initialized from a mapping object's + // (key, value) pairs. + // dict(seq) -> new dictionary initialized as if via: + dict() {} // new dict + + template <class T> + explicit dict(T const& data) + : base(object(data)) + { + } + + template<class T> + object get(T const& k) const + { + return base::get(object(k)); + } + + template<class T1, class T2> + object get(T1 const& k, T2 const& d) const + { + return base::get(object(k),object(d)); + } + + template<class T> + bool has_key(T const& k) const + { + return base::has_key(object(k)); + } + + template<class T> + object setdefault(T const& k) + { + return base::setdefault(object(k)); + } + + template<class T1, class T2> + object setdefault(T1 const& k, T2 const& d) + { + return base::setdefault(object(k),object(d)); + } + + template<class T> + void update(T const& E) + { + base::update(object(E)); + } + + public: // implementation detail -- for internal use only + BOOST_PYTHON_FORWARD_OBJECT_CONSTRUCTORS(dict, base) +}; + +// +// Converter Specializations +// +namespace converter +{ + template <> + struct object_manager_traits<dict> + : pytype_object_manager_traits<&PyDict_Type,dict> + { + }; +} + +}} // namespace boost::python + +#endif + diff --git a/boost/python/docstring_options.hpp b/boost/python/docstring_options.hpp new file mode 100644 index 0000000000..1914bd51a5 --- /dev/null +++ b/boost/python/docstring_options.hpp @@ -0,0 +1,127 @@ +// Copyright Ralf W. Grosse-Kunstleve 2006. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef DOCSTRING_OPTIONS_RWGK20060111_HPP +# define DOCSTRING_OPTIONS_RWGK20060111_HPP + +#include <boost/python/object/function.hpp> + +namespace boost { namespace python { + +// Note: the static data members are defined in object/function.cpp + +class BOOST_PYTHON_DECL docstring_options : boost::noncopyable +{ + public: + docstring_options(bool show_all=true) + { + previous_show_user_defined_ = show_user_defined_; + previous_show_py_signatures_ = show_py_signatures_; + previous_show_cpp_signatures_ = show_cpp_signatures_; + show_user_defined_ = show_all; + show_cpp_signatures_ = show_all; + show_py_signatures_ = show_all; + } + + docstring_options(bool show_user_defined, bool show_signatures) + { + previous_show_user_defined_ = show_user_defined_; + previous_show_cpp_signatures_ = show_cpp_signatures_; + previous_show_py_signatures_ = show_py_signatures_; + show_user_defined_ = show_user_defined; + show_cpp_signatures_ = show_signatures; + show_py_signatures_ = show_signatures; + } + + docstring_options(bool show_user_defined, bool show_py_signatures, bool show_cpp_signatures) + { + previous_show_user_defined_ = show_user_defined_; + previous_show_cpp_signatures_ = show_cpp_signatures_; + previous_show_py_signatures_ = show_py_signatures_; + show_user_defined_ = show_user_defined; + show_cpp_signatures_ = show_cpp_signatures; + show_py_signatures_ = show_py_signatures; + } + + ~docstring_options() + { + show_user_defined_ = previous_show_user_defined_; + show_cpp_signatures_ = previous_show_cpp_signatures_; + show_py_signatures_ = previous_show_py_signatures_; + } + + void + disable_user_defined() { show_user_defined_ = false; } + + void + enable_user_defined() { show_user_defined_ = true; } + + void + disable_py_signatures() + { + show_py_signatures_ = false; + } + + void + enable_py_signatures() + { + show_py_signatures_ = true; + } + + void + disable_cpp_signatures() + { + show_cpp_signatures_ = false; + } + + void + enable_cpp_signatures() + { + show_cpp_signatures_ = true; + } + + void + disable_signatures() + { + show_cpp_signatures_ = false; + show_py_signatures_ = false; + } + + void + enable_signatures() + { + show_cpp_signatures_ = true; + show_py_signatures_ = true; + } + + void + disable_all() + { + show_user_defined_ = false; + show_cpp_signatures_ = false; + show_py_signatures_ = false; + } + + void + enable_all() + { + show_user_defined_ = true; + show_cpp_signatures_ = true; + show_py_signatures_ = true; + } + + friend struct objects::function; + + private: + static volatile bool show_user_defined_; + static volatile bool show_cpp_signatures_; + static volatile bool show_py_signatures_; + bool previous_show_user_defined_; + bool previous_show_cpp_signatures_; + bool previous_show_py_signatures_; +}; + +}} // namespace boost::python + +#endif // DOCSTRING_OPTIONS_RWGK20060111_HPP diff --git a/boost/python/enum.hpp b/boost/python/enum.hpp new file mode 100644 index 0000000000..9631a0edc8 --- /dev/null +++ b/boost/python/enum.hpp @@ -0,0 +1,108 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef ENUM_DWA200298_HPP +# define ENUM_DWA200298_HPP + +# include <boost/python/detail/prefix.hpp> + +# include <boost/python/object/enum_base.hpp> +# include <boost/python/converter/rvalue_from_python_data.hpp> +# include <boost/python/converter/registered.hpp> + +namespace boost { namespace python { + +template <class T> +struct enum_ : public objects::enum_base +{ + typedef objects::enum_base base; + + // Declare a new enumeration type in the current scope() + enum_(char const* name, char const* doc = 0); + + // Add a new enumeration value with the given name and value. + inline enum_<T>& value(char const* name, T); + + // Add all of the defined enumeration values to the current scope with the + // same names used here. + inline enum_<T>& export_values(); + private: + static PyObject* to_python(void const* x); + static void* convertible_from_python(PyObject* obj); + static void construct(PyObject* obj, converter::rvalue_from_python_stage1_data* data); +}; + +template <class T> +inline enum_<T>::enum_(char const* name, char const* doc ) + : base( + name + , &enum_<T>::to_python + , &enum_<T>::convertible_from_python + , &enum_<T>::construct + , type_id<T>() + , doc + ) +{ +} + +// This is the conversion function that gets registered for converting +// these enums to Python. +template <class T> +PyObject* enum_<T>::to_python(void const* x) +{ + return base::to_python( + converter::registered<T>::converters.m_class_object + , static_cast<long>(*(T const*)x)); +} + +// +// The following two static functions serve as the elements of an +// rvalue from_python converter for the enumeration type. +// + +// This checks that a given Python object can be converted to the +// enumeration type. +template <class T> +void* enum_<T>::convertible_from_python(PyObject* obj) +{ + return PyObject_IsInstance( + obj + , upcast<PyObject>( + converter::registered<T>::converters.m_class_object)) + + ? obj : 0; +} + +// Constructs an instance of the enumeration type in the from_python +// data. +template <class T> +void enum_<T>::construct(PyObject* obj, converter::rvalue_from_python_stage1_data* data) +{ +#if PY_VERSION_HEX >= 0x03000000 + T x = static_cast<T>(PyLong_AS_LONG(obj)); +#else + T x = static_cast<T>(PyInt_AS_LONG(obj)); +#endif + void* const storage = ((converter::rvalue_from_python_storage<T>*)data)->storage.bytes; + new (storage) T(x); + data->convertible = storage; +} + +template <class T> +inline enum_<T>& enum_<T>::value(char const* name, T x) +{ + this->add_value(name, static_cast<long>(x)); + return *this; +} + +template <class T> +inline enum_<T>& enum_<T>::export_values() +{ + this->base::export_values(); + return *this; +} + +}} // namespace boost::python + +#endif // ENUM_DWA200298_HPP diff --git a/boost/python/errors.hpp b/boost/python/errors.hpp new file mode 100644 index 0000000000..72960d9ea2 --- /dev/null +++ b/boost/python/errors.hpp @@ -0,0 +1,55 @@ +// (C) Copyright David Abrahams 2000. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// The author gratefully acknowleges the support of Dragon Systems, Inc., in +// producing this work. + +#ifndef ERRORS_DWA052500_H_ +# define ERRORS_DWA052500_H_ + +# include <boost/python/detail/prefix.hpp> +# include <boost/function/function0.hpp> + +namespace boost { namespace python { + +struct BOOST_PYTHON_DECL_EXCEPTION error_already_set +{ + virtual ~error_already_set(); +}; + +// Handles exceptions caught just before returning to Python code. +// Returns true iff an exception was caught. +BOOST_PYTHON_DECL bool handle_exception_impl(function0<void>); + +template <class T> +bool handle_exception(T f) +{ + return handle_exception_impl(function0<void>(boost::ref(f))); +} + +namespace detail { inline void rethrow() { throw; } } + +inline void handle_exception() +{ + handle_exception(detail::rethrow); +} + +BOOST_PYTHON_DECL void throw_error_already_set(); + +template <class T> +inline T* expect_non_null(T* x) +{ + if (x == 0) + throw_error_already_set(); + return x; +} + +// Return source if it is an instance of pytype; throw an appropriate +// exception otherwise. +BOOST_PYTHON_DECL PyObject* pytype_check(PyTypeObject* pytype, PyObject* source); + +}} // namespace boost::python + +#endif // ERRORS_DWA052500_H_ diff --git a/boost/python/exception_translator.hpp b/boost/python/exception_translator.hpp new file mode 100644 index 0000000000..eb72da62a1 --- /dev/null +++ b/boost/python/exception_translator.hpp @@ -0,0 +1,27 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef EXCEPTION_TRANSLATOR_DWA2002810_HPP +# define EXCEPTION_TRANSLATOR_DWA2002810_HPP + +# include <boost/python/detail/prefix.hpp> + +# include <boost/bind.hpp> +# include <boost/type.hpp> +# include <boost/python/detail/translate_exception.hpp> +# include <boost/python/detail/exception_handler.hpp> + +namespace boost { namespace python { + +template <class ExceptionType, class Translate> +void register_exception_translator(Translate translate, boost::type<ExceptionType>* = 0) +{ + detail::register_exception_handler( + boost::bind<bool>(detail::translate_exception<ExceptionType,Translate>(), _1, _2, translate) + ); +} + +}} // namespace boost::python + +#endif // EXCEPTION_TRANSLATOR_DWA2002810_HPP diff --git a/boost/python/exec.hpp b/boost/python/exec.hpp new file mode 100644 index 0000000000..3ed1e15ce9 --- /dev/null +++ b/boost/python/exec.hpp @@ -0,0 +1,47 @@ +// Copyright Stefan Seefeld 2005. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef EXEC_SS20050616_HPP +# define EXEC_SS20050616_HPP + +# include <boost/python/object.hpp> +# include <boost/python/str.hpp> + +namespace boost +{ +namespace python +{ + +// Evaluate python expression from str. +// global and local are the global and local scopes respectively, +// used during evaluation. +object +BOOST_PYTHON_DECL +eval(str string, object global = object(), object local = object()); + +// Execute an individual python statement from str. +// global and local are the global and local scopes respectively, +// used during execution. +object +BOOST_PYTHON_DECL +exec_statement(str string, object global = object(), object local = object()); + +// Execute python source code from str. +// global and local are the global and local scopes respectively, +// used during execution. +object +BOOST_PYTHON_DECL +exec(str string, object global = object(), object local = object()); + +// Execute python source code from file filename. +// global and local are the global and local scopes respectively, +// used during execution. +object +BOOST_PYTHON_DECL +exec_file(str filename, object global = object(), object local = object()); + +} +} + +#endif diff --git a/boost/python/extract.hpp b/boost/python/extract.hpp new file mode 100644 index 0000000000..4e876f5009 --- /dev/null +++ b/boost/python/extract.hpp @@ -0,0 +1,261 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef EXTRACT_DWA200265_HPP +# define EXTRACT_DWA200265_HPP + +# include <boost/python/detail/prefix.hpp> + +# include <boost/python/converter/object_manager.hpp> +# include <boost/python/converter/from_python.hpp> +# include <boost/python/converter/rvalue_from_python_data.hpp> +# include <boost/python/converter/registered.hpp> +# include <boost/python/converter/registered_pointee.hpp> + +# include <boost/python/object_core.hpp> +# include <boost/python/refcount.hpp> + +# include <boost/python/detail/copy_ctor_mutates_rhs.hpp> +# include <boost/python/detail/void_ptr.hpp> +# include <boost/python/detail/void_return.hpp> +# include <boost/utility.hpp> +# include <boost/call_traits.hpp> + +#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) || BOOST_WORKAROUND(BOOST_INTEL_WIN, <= 900) +// workaround for VC++ 6.x or 7.0 +# define BOOST_EXTRACT_WORKAROUND () +#else +# define BOOST_EXTRACT_WORKAROUND +#endif + +namespace boost { namespace python { + +namespace api +{ + class object; +} + +namespace converter +{ + template <class Ptr> + struct extract_pointer + { + typedef Ptr result_type; + extract_pointer(PyObject*); + + bool check() const; + Ptr operator()() const; + + private: + PyObject* m_source; + void* m_result; + }; + + template <class Ref> + struct extract_reference + { + typedef Ref result_type; + extract_reference(PyObject*); + + bool check() const; + Ref operator()() const; + + private: + PyObject* m_source; + void* m_result; + }; + + template <class T> + struct extract_rvalue : private noncopyable + { + typedef typename mpl::if_< + python::detail::copy_ctor_mutates_rhs<T> + , T& + , typename call_traits<T>::param_type + >::type result_type; + + extract_rvalue(PyObject*); + + bool check() const; + result_type operator()() const; + private: + PyObject* m_source; + mutable rvalue_from_python_data<T> m_data; + }; + + template <class T> + struct extract_object_manager + { + typedef T result_type; + extract_object_manager(PyObject*); + + bool check() const; + result_type operator()() const; + private: + PyObject* m_source; + }; + + template <class T> + struct select_extract + { + BOOST_STATIC_CONSTANT( + bool, obj_mgr = is_object_manager<T>::value); + + BOOST_STATIC_CONSTANT( + bool, ptr = is_pointer<T>::value); + + BOOST_STATIC_CONSTANT( + bool, ref = is_reference<T>::value); + + typedef typename mpl::if_c< + obj_mgr + , extract_object_manager<T> + , typename mpl::if_c< + ptr + , extract_pointer<T> + , typename mpl::if_c< + ref + , extract_reference<T> + , extract_rvalue<T> + >::type + >::type + >::type type; + }; +} + +template <class T> +struct extract + : converter::select_extract<T>::type +{ + private: + typedef typename converter::select_extract<T>::type base; + public: + typedef typename base::result_type result_type; + + operator result_type() const + { + return (*this)(); + } + + extract(PyObject*); + extract(api::object const&); +}; + +// +// Implementations +// +template <class T> +inline extract<T>::extract(PyObject* o) + : base(o) +{ +} + +template <class T> +inline extract<T>::extract(api::object const& o) + : base(o.ptr()) +{ +} + +namespace converter +{ + template <class T> + inline extract_rvalue<T>::extract_rvalue(PyObject* x) + : m_source(x) + , m_data( + (rvalue_from_python_stage1)(x, registered<T>::converters) + ) + { + } + + template <class T> + inline bool + extract_rvalue<T>::check() const + { + return m_data.stage1.convertible; + } + + template <class T> + inline typename extract_rvalue<T>::result_type + extract_rvalue<T>::operator()() const + { + return *(T*)( + // Only do the stage2 conversion once + m_data.stage1.convertible == m_data.storage.bytes + ? m_data.storage.bytes + : (rvalue_from_python_stage2)(m_source, m_data.stage1, registered<T>::converters) + ); + } + + template <class Ref> + inline extract_reference<Ref>::extract_reference(PyObject* obj) + : m_source(obj) + , m_result( + (get_lvalue_from_python)(obj, registered<Ref>::converters) + ) + { + } + + template <class Ref> + inline bool extract_reference<Ref>::check() const + { + return m_result != 0; + } + + template <class Ref> + inline Ref extract_reference<Ref>::operator()() const + { + if (m_result == 0) + (throw_no_reference_from_python)(m_source, registered<Ref>::converters); + + return python::detail::void_ptr_to_reference(m_result, (Ref(*)())0); + } + + template <class Ptr> + inline extract_pointer<Ptr>::extract_pointer(PyObject* obj) + : m_source(obj) + , m_result( + obj == Py_None ? 0 : (get_lvalue_from_python)(obj, registered_pointee<Ptr>::converters) + ) + { + } + + template <class Ptr> + inline bool extract_pointer<Ptr>::check() const + { + return m_source == Py_None || m_result != 0; + } + + template <class Ptr> + inline Ptr extract_pointer<Ptr>::operator()() const + { + if (m_result == 0 && m_source != Py_None) + (throw_no_pointer_from_python)(m_source, registered_pointee<Ptr>::converters); + + return Ptr(m_result); + } + + template <class T> + inline extract_object_manager<T>::extract_object_manager(PyObject* obj) + : m_source(obj) + { + } + + template <class T> + inline bool extract_object_manager<T>::check() const + { + return object_manager_traits<T>::check(m_source); + } + + template <class T> + inline T extract_object_manager<T>::operator()() const + { + return T( + object_manager_traits<T>::adopt(python::incref(m_source)) + ); + } +} + +}} // namespace boost::python::converter + +#endif // EXTRACT_DWA200265_HPP diff --git a/boost/python/handle.hpp b/boost/python/handle.hpp new file mode 100644 index 0000000000..461a219ad8 --- /dev/null +++ b/boost/python/handle.hpp @@ -0,0 +1,264 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef HANDLE_DWA200269_HPP +# define HANDLE_DWA200269_HPP + +# include <boost/python/detail/prefix.hpp> + +# include <boost/python/cast.hpp> +# include <boost/python/errors.hpp> +# include <boost/python/borrowed.hpp> +# include <boost/python/handle_fwd.hpp> +# include <boost/python/refcount.hpp> +# include <boost/python/tag.hpp> +# include <boost/python/detail/raw_pyobject.hpp> + +namespace boost { namespace python { + +template <class T> struct null_ok; + +template <class T> +inline null_ok<T>* allow_null(T* p) +{ + return (null_ok<T>*)p; +} + +namespace detail +{ + template <class T> + inline T* manage_ptr(detail::borrowed<null_ok<T> >* p, int) + { + return python::xincref((T*)p); + } + + template <class T> + inline T* manage_ptr(null_ok<detail::borrowed<T> >* p, int) + { + return python::xincref((T*)p); + } + + template <class T> + inline T* manage_ptr(detail::borrowed<T>* p, long) + { + return python::incref(expect_non_null((T*)p)); + } + + template <class T> + inline T* manage_ptr(null_ok<T>* p, long) + { + return (T*)p; + } + + template <class T> + inline T* manage_ptr(T* p, ...) + { + return expect_non_null(p); + } +} + +template <class T> +class handle +{ + typedef T* (handle::* bool_type )() const; + + public: // types + typedef T element_type; + + public: // member functions + handle(); + ~handle(); + + template <class Y> + explicit handle(Y* p) + : m_p( + python::upcast<T>( + detail::manage_ptr(p, 0) + ) + ) + { + } + + handle& operator=(handle const& r) + { + python::xdecref(m_p); + m_p = python::xincref(r.m_p); + return *this; + } + +#if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1300) + + template<typename Y> + handle& operator=(handle<Y> const & r) // never throws + { + python::xdecref(m_p); + m_p = python::xincref(python::upcast<T>(r.get())); + return *this; + } + +#endif + + template <typename Y> + handle(handle<Y> const& r) + : m_p(python::xincref(python::upcast<T>(r.get()))) + { + } + + handle(handle const& r) + : m_p(python::xincref(r.m_p)) + { + } + + T* operator-> () const; + T& operator* () const; + T* get() const; + T* release(); + void reset(); + + operator bool_type() const // never throws + { + return m_p ? &handle<T>::get : 0; + } + bool operator! () const; // never throws + + public: // implementation details -- do not touch + // Defining this in the class body suppresses a VC7 link failure + inline handle(detail::borrowed_reference x) + : m_p( + python::incref( + downcast<T>((PyObject*)x) + )) + { + } + + private: // data members + T* m_p; +}; + +#ifdef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP +} // namespace python +#endif + +template<class T> inline T * get_pointer(python::handle<T> const & p) +{ + return p.get(); +} + +#ifdef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP +namespace python { +#else + +// We don't want get_pointer above to hide the others +using boost::get_pointer; + +#endif + +typedef handle<PyTypeObject> type_handle; + +// +// Compile-time introspection +// +# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +template<typename T> +class is_handle +{ + public: + BOOST_STATIC_CONSTANT(bool, value = false); +}; + +template<typename T> +class is_handle<handle<T> > +{ + public: + BOOST_STATIC_CONSTANT(bool, value = true); +}; +# else +namespace detail +{ + typedef char (&yes_handle_t)[1]; + typedef char (&no_handle_t)[2]; + + no_handle_t is_handle_test(...); + + template<typename T> + yes_handle_t is_handle_test(boost::type< handle<T> >); +} + +template<typename T> +class is_handle +{ + public: + BOOST_STATIC_CONSTANT( + bool, value = ( + sizeof(detail::is_handle_test(boost::type<T>())) + == sizeof(detail::yes_handle_t))); +}; +# endif + +// +// implementations +// +template <class T> +inline handle<T>::handle() + : m_p(0) +{ +} + +template <class T> +inline handle<T>::~handle() +{ + python::xdecref(m_p); +} + +template <class T> +inline T* handle<T>::operator->() const +{ + return m_p; +} + +template <class T> +inline T& handle<T>::operator*() const +{ + return *m_p; +} + +template <class T> +inline T* handle<T>::get() const +{ + return m_p; +} + +template <class T> +inline bool handle<T>::operator!() const +{ + return m_p == 0; +} + +template <class T> +inline T* handle<T>::release() +{ + T* result = m_p; + m_p = 0; + return result; +} + +template <class T> +inline void handle<T>::reset() +{ + python::xdecref(m_p); + m_p = 0; +} + +// Because get_managed_object must return a non-null PyObject*, we +// return Py_None if the handle is null. +template <class T> +inline PyObject* get_managed_object(handle<T> const& h, tag_t) +{ + return h.get() ? python::upcast<PyObject>(h.get()) : Py_None; +} + +}} // namespace boost::python + + +#endif // HANDLE_DWA200269_HPP diff --git a/boost/python/handle_fwd.hpp b/boost/python/handle_fwd.hpp new file mode 100644 index 0000000000..5987ec4fdb --- /dev/null +++ b/boost/python/handle_fwd.hpp @@ -0,0 +1,16 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef HANDLE_FWD_DWA2002615_HPP +# define HANDLE_FWD_DWA2002615_HPP + +# include <boost/python/detail/prefix.hpp> + +namespace boost { namespace python { + +template <class T = PyObject> class handle; + +}} // namespace boost::python + +#endif // HANDLE_FWD_DWA2002615_HPP diff --git a/boost/python/has_back_reference.hpp b/boost/python/has_back_reference.hpp new file mode 100644 index 0000000000..67fe24c5cf --- /dev/null +++ b/boost/python/has_back_reference.hpp @@ -0,0 +1,24 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef HAS_BACK_REFERENCE_DWA2002323_HPP +# define HAS_BACK_REFERENCE_DWA2002323_HPP + +# include <boost/python/detail/prefix.hpp> +# include <boost/mpl/bool.hpp> + +namespace boost { namespace python { + +// traits class which users can specialize to indicate that a class +// contains a back-reference to its owning PyObject* +template <class T> +struct has_back_reference + : mpl::false_ +{ +}; + + +}} // namespace boost::python + +#endif // HAS_BACK_REFERENCE_DWA2002323_HPP diff --git a/boost/python/implicit.hpp b/boost/python/implicit.hpp new file mode 100644 index 0000000000..4d01b2fb22 --- /dev/null +++ b/boost/python/implicit.hpp @@ -0,0 +1,36 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef IMPLICIT_DWA2002325_HPP +# define IMPLICIT_DWA2002325_HPP + +# include <boost/python/detail/prefix.hpp> +# include <boost/type.hpp> +# include <boost/python/converter/implicit.hpp> +# include <boost/python/converter/registry.hpp> +#ifndef BOOST_PYTHON_NO_PY_SIGNATURES +# include <boost/python/converter/pytype_function.hpp> +#endif +# include <boost/python/type_id.hpp> + +namespace boost { namespace python { + +template <class Source, class Target> +void implicitly_convertible(boost::type<Source>* = 0, boost::type<Target>* = 0) +{ + typedef converter::implicit<Source,Target> functions; + + converter::registry::push_back( + &functions::convertible + , &functions::construct + , type_id<Target>() +#ifndef BOOST_PYTHON_NO_PY_SIGNATURES + , &converter::expected_from_python_type_direct<Source>::get_pytype +#endif + ); +} + +}} // namespace boost::python + +#endif // IMPLICIT_DWA2002325_HPP diff --git a/boost/python/import.hpp b/boost/python/import.hpp new file mode 100644 index 0000000000..45c02a9366 --- /dev/null +++ b/boost/python/import.hpp @@ -0,0 +1,22 @@ +// Copyright Stefan Seefeld 2005. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef IMPORT_SS20050624_HPP +# define IMPORT_SS20050624_HPP + +# include <boost/python/object.hpp> +# include <boost/python/str.hpp> + +namespace boost +{ +namespace python +{ + +// Import the named module and return a reference to it. +object BOOST_PYTHON_DECL import(str name); + +} +} + +#endif diff --git a/boost/python/init.hpp b/boost/python/init.hpp new file mode 100644 index 0000000000..6598fd3547 --- /dev/null +++ b/boost/python/init.hpp @@ -0,0 +1,421 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright David Abrahams 2002, Joel de Guzman, 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +/////////////////////////////////////////////////////////////////////////////// +#ifndef INIT_JDG20020820_HPP +#define INIT_JDG20020820_HPP + +# include <boost/python/detail/prefix.hpp> + +#include <boost/python/detail/type_list.hpp> +#include <boost/python/args_fwd.hpp> +#include <boost/python/detail/make_keyword_range_fn.hpp> +#include <boost/python/def_visitor.hpp> + +#include <boost/mpl/if.hpp> +#include <boost/mpl/eval_if.hpp> +#include <boost/mpl/size.hpp> +#include <boost/mpl/iterator_range.hpp> +#include <boost/mpl/empty.hpp> +#include <boost/mpl/begin_end.hpp> +#include <boost/mpl/bool.hpp> +#include <boost/mpl/prior.hpp> +#include <boost/mpl/joint_view.hpp> +#include <boost/mpl/back.hpp> + +#include <boost/type_traits/is_same.hpp> + +#include <boost/preprocessor/enum_params_with_a_default.hpp> +#include <boost/preprocessor/enum_params.hpp> + +#include <utility> + +/////////////////////////////////////////////////////////////////////////////// +#define BOOST_PYTHON_OVERLOAD_TYPES_WITH_DEFAULT \ + BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT( \ + BOOST_PYTHON_MAX_ARITY, \ + class T, \ + mpl::void_) \ + +#define BOOST_PYTHON_OVERLOAD_TYPES \ + BOOST_PP_ENUM_PARAMS_Z(1, \ + BOOST_PYTHON_MAX_ARITY, \ + class T) \ + +#define BOOST_PYTHON_OVERLOAD_ARGS \ + BOOST_PP_ENUM_PARAMS_Z(1, \ + BOOST_PYTHON_MAX_ARITY, \ + T) \ + +/////////////////////////////////////////////////////////////////////////////// +namespace boost { namespace python { + +template <BOOST_PYTHON_OVERLOAD_TYPES_WITH_DEFAULT> +class init; // forward declaration + + +template <BOOST_PYTHON_OVERLOAD_TYPES_WITH_DEFAULT> +struct optional; // forward declaration + +namespace detail +{ + namespace error + { + template <int keywords, int init_args> + struct more_keywords_than_init_arguments + { + typedef char too_many_keywords[init_args - keywords >= 0 ? 1 : -1]; + }; + } + + // is_optional<T>::value + // + // This metaprogram checks if T is an optional + // +#if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) + + template <class T> + struct is_optional { + + private: + + template <BOOST_PYTHON_OVERLOAD_TYPES> + static boost::type_traits::yes_type f(optional<BOOST_PYTHON_OVERLOAD_ARGS>); + static boost::type_traits::no_type f(...); + static T t(); + + public: + + BOOST_STATIC_CONSTANT( + bool, value = + sizeof(f(t())) == sizeof(::boost::type_traits::yes_type)); + typedef mpl::bool_<value> type; + }; + +#else + + template <class T> + struct is_optional + : mpl::false_ + {}; + + template <BOOST_PYTHON_OVERLOAD_TYPES> + struct is_optional<optional<BOOST_PYTHON_OVERLOAD_ARGS> > + : mpl::true_ + {}; + +#endif + + template <int NDefaults> + struct define_class_init_helper; + +} // namespace detail + +template <class DerivedT> +struct init_base : def_visitor<DerivedT> +{ + init_base(char const* doc_, detail::keyword_range const& keywords_) + : m_doc(doc_), m_keywords(keywords_) + {} + + init_base(char const* doc_) + : m_doc(doc_) + {} + + DerivedT const& derived() const + { + return *static_cast<DerivedT const*>(this); + } + + char const* doc_string() const + { + return m_doc; + } + + detail::keyword_range const& keywords() const + { + return m_keywords; + } + + static default_call_policies call_policies() + { + return default_call_policies(); + } + + private: + // visit + // + // Defines a set of n_defaults + 1 constructors for its + // class_<...> argument. Each constructor after the first has + // one less argument to its right. Example: + // + // init<int, optional<char, long, double> > + // + // Defines: + // + // __init__(int, char, long, double) + // __init__(int, char, long) + // __init__(int, char) + // __init__(int) + template <class classT> + void visit(classT& cl) const + { + typedef typename DerivedT::signature signature; + typedef typename DerivedT::n_arguments n_arguments; + typedef typename DerivedT::n_defaults n_defaults; + + detail::define_class_init_helper<n_defaults::value>::apply( + cl + , derived().call_policies() + , signature() + , n_arguments() + , derived().doc_string() + , derived().keywords()); + } + + friend class python::def_visitor_access; + + private: // data members + char const* m_doc; + detail::keyword_range m_keywords; +}; + +template <class CallPoliciesT, class InitT> +class init_with_call_policies + : public init_base<init_with_call_policies<CallPoliciesT, InitT> > +{ + typedef init_base<init_with_call_policies<CallPoliciesT, InitT> > base; + public: + typedef typename InitT::n_arguments n_arguments; + typedef typename InitT::n_defaults n_defaults; + typedef typename InitT::signature signature; + + init_with_call_policies( + CallPoliciesT const& policies_ + , char const* doc_ + , detail::keyword_range const& keywords + ) + : base(doc_, keywords) + , m_policies(policies_) + {} + + CallPoliciesT const& call_policies() const + { + return this->m_policies; + } + + private: // data members + CallPoliciesT m_policies; +}; + +// +// drop1<S> is the initial length(S) elements of S +// +namespace detail +{ + template <class S> + struct drop1 + : mpl::iterator_range< + typename mpl::begin<S>::type + , typename mpl::prior< + typename mpl::end<S>::type + >::type + > + {}; +} + +template <BOOST_PYTHON_OVERLOAD_TYPES> +class init : public init_base<init<BOOST_PYTHON_OVERLOAD_ARGS> > +{ + typedef init_base<init<BOOST_PYTHON_OVERLOAD_ARGS> > base; + public: + typedef init<BOOST_PYTHON_OVERLOAD_ARGS> self_t; + + init(char const* doc_ = 0) + : base(doc_) + { + } + + template <std::size_t N> + init(char const* doc_, detail::keywords<N> const& kw) + : base(doc_, kw.range()) + { + typedef typename detail::error::more_keywords_than_init_arguments< + N, n_arguments::value + 1 + >::too_many_keywords assertion; + } + + template <std::size_t N> + init(detail::keywords<N> const& kw, char const* doc_ = 0) + : base(doc_, kw.range()) + { + typedef typename detail::error::more_keywords_than_init_arguments< + N, n_arguments::value + 1 + >::too_many_keywords assertion; + } + + template <class CallPoliciesT> + init_with_call_policies<CallPoliciesT, self_t> + operator[](CallPoliciesT const& policies) const + { + return init_with_call_policies<CallPoliciesT, self_t>( + policies, this->doc_string(), this->keywords()); + } + + typedef detail::type_list<BOOST_PYTHON_OVERLOAD_ARGS> signature_; + + typedef detail::is_optional< + typename mpl::eval_if< + mpl::empty<signature_> + , mpl::false_ + , mpl::back<signature_> + >::type + > back_is_optional; + + typedef typename mpl::eval_if< + back_is_optional + , mpl::back<signature_> + , mpl::vector0<> + >::type optional_args; + + typedef typename mpl::eval_if< + back_is_optional + , mpl::if_< + mpl::empty<optional_args> + , detail::drop1<signature_> + , mpl::joint_view< + detail::drop1<signature_> + , optional_args + > + > + , signature_ + >::type signature; + + // TODO: static assert to make sure there are no other optional elements + + // Count the number of default args + typedef mpl::size<optional_args> n_defaults; + typedef mpl::size<signature> n_arguments; +}; + +/////////////////////////////////////////////////////////////////////////////// +// +// optional +// +// optional<T0...TN>::type returns a typelist. +// +/////////////////////////////////////////////////////////////////////////////// +template <BOOST_PYTHON_OVERLOAD_TYPES> +struct optional + : detail::type_list<BOOST_PYTHON_OVERLOAD_ARGS> +{ +}; + +namespace detail +{ + template <class ClassT, class CallPoliciesT, class Signature, class NArgs> + inline void def_init_aux( + ClassT& cl + , Signature const& + , NArgs + , CallPoliciesT const& policies + , char const* doc + , detail::keyword_range const& keywords_ + ) + { + cl.def( + "__init__" + , detail::make_keyword_range_constructor<Signature,NArgs>( + policies + , keywords_ + , (typename ClassT::metadata::holder*)0 + ) + , doc + ); + } + + /////////////////////////////////////////////////////////////////////////////// + // + // define_class_init_helper<N>::apply + // + // General case + // + // Accepts a class_ and an arguments list. Defines a constructor + // for the class given the arguments and recursively calls + // define_class_init_helper<N-1>::apply with one fewer argument (the + // rightmost argument is shaved off) + // + /////////////////////////////////////////////////////////////////////////////// + template <int NDefaults> + struct define_class_init_helper + { + + template <class ClassT, class CallPoliciesT, class Signature, class NArgs> + static void apply( + ClassT& cl + , CallPoliciesT const& policies + , Signature const& args + , NArgs + , char const* doc + , detail::keyword_range keywords) + { + detail::def_init_aux(cl, args, NArgs(), policies, doc, keywords); + + if (keywords.second > keywords.first) + --keywords.second; + + typedef typename mpl::prior<NArgs>::type next_nargs; + define_class_init_helper<NDefaults-1>::apply( + cl, policies, Signature(), next_nargs(), doc, keywords); + } + }; + + /////////////////////////////////////////////////////////////////////////////// + // + // define_class_init_helper<0>::apply + // + // Terminal case + // + // Accepts a class_ and an arguments list. Defines a constructor + // for the class given the arguments. + // + /////////////////////////////////////////////////////////////////////////////// + template <> + struct define_class_init_helper<0> { + + template <class ClassT, class CallPoliciesT, class Signature, class NArgs> + static void apply( + ClassT& cl + , CallPoliciesT const& policies + , Signature const& args + , NArgs + , char const* doc + , detail::keyword_range const& keywords) + { + detail::def_init_aux(cl, args, NArgs(), policies, doc, keywords); + } + }; +} + +}} // namespace boost::python + +#undef BOOST_PYTHON_OVERLOAD_TYPES_WITH_DEFAULT +#undef BOOST_PYTHON_OVERLOAD_TYPES +#undef BOOST_PYTHON_OVERLOAD_ARGS +#undef BOOST_PYTHON_IS_OPTIONAL_VALUE +#undef BOOST_PYTHON_APPEND_TO_INIT + +/////////////////////////////////////////////////////////////////////////////// +#endif // INIT_JDG20020820_HPP + + + + + + + + diff --git a/boost/python/instance_holder.hpp b/boost/python/instance_holder.hpp new file mode 100644 index 0000000000..0916348ef6 --- /dev/null +++ b/boost/python/instance_holder.hpp @@ -0,0 +1,63 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef INSTANCE_HOLDER_DWA2002517_HPP +# define INSTANCE_HOLDER_DWA2002517_HPP + +# include <boost/python/detail/prefix.hpp> + +# include <boost/utility.hpp> +# include <boost/python/type_id.hpp> +# include <cstddef> + +namespace boost { namespace python { + +// Base class for all holders +struct BOOST_PYTHON_DECL instance_holder : private noncopyable +{ + public: + instance_holder(); + virtual ~instance_holder(); + + // return the next holder in a chain + instance_holder* next() const; + + // When the derived holder actually holds by [smart] pointer and + // null_ptr_only is set, only report that the type is held when + // the pointer is null. This is needed for proper shared_ptr + // support, to prevent holding shared_ptrs from being found when + // converting from python so that we can use the conversion method + // that always holds the Python object. + virtual void* holds(type_info, bool null_ptr_only) = 0; + + void install(PyObject* inst) throw(); + + // These functions should probably be located elsewhere. + + // Allocate storage for an object of the given size at the given + // offset in the Python instance<> object if bytes are available + // there. Otherwise allocate size bytes of heap memory. + static void* allocate(PyObject*, std::size_t offset, std::size_t size); + + // Deallocate storage from the heap if it was not carved out of + // the given Python object by allocate(), above. + static void deallocate(PyObject*, void* storage) throw(); + private: + instance_holder* m_next; +}; + +// This macro is needed for implementation of derived holders +# define BOOST_PYTHON_UNFORWARD(N,ignored) (typename unforward<A##N>::type)(a##N) + +// +// implementation +// +inline instance_holder* instance_holder::next() const +{ + return m_next; +} + +}} // namespace boost::python + +#endif // INSTANCE_HOLDER_DWA2002517_HPP diff --git a/boost/python/iterator.hpp b/boost/python/iterator.hpp new file mode 100644 index 0000000000..a64a920735 --- /dev/null +++ b/boost/python/iterator.hpp @@ -0,0 +1,137 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef ITERATOR_DWA2002512_HPP +# define ITERATOR_DWA2002512_HPP + +# include <boost/python/detail/prefix.hpp> + +# include <boost/python/detail/target.hpp> +# include <boost/python/object/iterator.hpp> +# include <boost/python/object_core.hpp> + +# include <boost/type_traits/cv_traits.hpp> +# include <boost/type_traits/transform_traits.hpp> + +# if defined(BOOST_MSVC) && (BOOST_MSVC == 1400) /* +> warning C4180: qualifier applied to function type has no meaning; ignored +Peter Dimov wrote: +This warning is caused by an overload resolution bug in VC8 that cannot be +worked around and will probably not be fixed by MS in the VC8 line. The +problematic overload is only instantiated and never called, and the code +works correctly. */ +# pragma warning(disable: 4180) +# endif + +# include <boost/bind.hpp> +# include <boost/bind/protect.hpp> + +namespace boost { namespace python { + +namespace detail +{ + // Adds an additional layer of binding to + // objects::make_iterator(...), which allows us to pass member + // function and member data pointers. + template <class Target, class Accessor1, class Accessor2, class NextPolicies> + inline object make_iterator( + Accessor1 get_start + , Accessor2 get_finish + , NextPolicies next_policies + , Target&(*)() + ) + { + return objects::make_iterator_function<Target>( + boost::protect(boost::bind(get_start, _1)) + , boost::protect(boost::bind(get_finish, _1)) + , next_policies + ); + } + + // Guts of template class iterators<>, below. + template <bool const_ = false> + struct iterators_impl + { + template <class T> + struct apply + { + typedef typename T::iterator iterator; + static iterator begin(T& x) { return x.begin(); } + static iterator end(T& x) { return x.end(); } + }; + }; + + template <> + struct iterators_impl<true> + { + template <class T> + struct apply + { + typedef typename T::const_iterator iterator; + static iterator begin(T& x) { return x.begin(); } + static iterator end(T& x) { return x.end(); } + }; + }; +} + +// An "ordinary function generator" which contains static begin(x) and +// end(x) functions that invoke T::begin() and T::end(), respectively. +template <class T> +struct iterators + : detail::iterators_impl< + boost::is_const<T>::value + >::template apply<T> +{ +}; + +// Create an iterator-building function which uses the given +// accessors. Deduce the Target type from the accessors. The iterator +// returns copies of the inderlying elements. +template <class Accessor1, class Accessor2> +object range(Accessor1 start, Accessor2 finish) +{ + return detail::make_iterator( + start, finish + , objects::default_iterator_call_policies() + , detail::target(start) + ); +} + +// Create an iterator-building function which uses the given accessors +// and next() policies. Deduce the Target type. +template <class NextPolicies, class Accessor1, class Accessor2> +object range(Accessor1 start, Accessor2 finish, NextPolicies* = 0) +{ + return detail::make_iterator(start, finish, NextPolicies(), detail::target(start)); +} + +// Create an iterator-building function which uses the given accessors +// and next() policies, operating on the given Target type +template <class NextPolicies, class Target, class Accessor1, class Accessor2> +object range(Accessor1 start, Accessor2 finish, NextPolicies* = 0, boost::type<Target>* = 0) +{ + // typedef typename add_reference<Target>::type target; + return detail::make_iterator(start, finish, NextPolicies(), (Target&(*)())0); +} + +// A Python callable object which produces an iterator traversing +// [x.begin(), x.end()), where x is an instance of the Container +// type. NextPolicies are used as the CallPolicies for the iterator's +// next() function. +template <class Container + , class NextPolicies = objects::default_iterator_call_policies> +struct iterator : object +{ + iterator() + : object( + python::range<NextPolicies>( + &iterators<Container>::begin, &iterators<Container>::end + )) + { + } +}; + +}} // namespace boost::python + +#endif // ITERATOR_DWA2002512_HPP diff --git a/boost/python/list.hpp b/boost/python/list.hpp new file mode 100644 index 0000000000..10fd40fda5 --- /dev/null +++ b/boost/python/list.hpp @@ -0,0 +1,148 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef LIST_DWA2002627_HPP +# define LIST_DWA2002627_HPP + +# include <boost/python/detail/prefix.hpp> + +# include <boost/python/object.hpp> +# include <boost/python/converter/pytype_object_mgr_traits.hpp> +# include <boost/python/ssize_t.hpp> + +namespace boost { namespace python { + +namespace detail +{ + struct BOOST_PYTHON_DECL list_base : object + { + void append(object_cref); // append object to end + + ssize_t count(object_cref value) const; // return number of occurrences of value + + void extend(object_cref sequence); // extend list by appending sequence elements + + long index(object_cref value) const; // return index of first occurrence of value + + void insert(ssize_t index, object_cref); // insert object before index + void insert(object const& index, object_cref); + + object pop(); // remove and return item at index (default last) + object pop(ssize_t index); + object pop(object const& index); + + void remove(object_cref value); // remove first occurrence of value + + void reverse(); // reverse *IN PLACE* + + void sort(); // sort *IN PLACE*; if given, cmpfunc(x, y) -> -1, 0, 1 +#if PY_VERSION_HEX >= 0x03000000 + void sort(args_proxy const &args, + kwds_proxy const &kwds); +#else + void sort(object_cref cmpfunc); +#endif + + protected: + list_base(); // new list + explicit list_base(object_cref sequence); // new list initialized from sequence's items + + BOOST_PYTHON_FORWARD_OBJECT_CONSTRUCTORS(list_base, object) + private: + static detail::new_non_null_reference call(object const&); + }; +} + +class list : public detail::list_base +{ + typedef detail::list_base base; + public: + list() {} // new list + + template <class T> + explicit list(T const& sequence) + : base(object(sequence)) + { + } + + template <class T> + void append(T const& x) + { + base::append(object(x)); + } + + template <class T> + long count(T const& value) const + { + return base::count(object(value)); + } + + template <class T> + void extend(T const& x) + { + base::extend(object(x)); + } + + template <class T> + long index(T const& x) const + { + return base::index(object(x)); + } + + template <class T> + void insert(ssize_t index, T const& x) // insert object before index + { + base::insert(index, object(x)); + } + + template <class T> + void insert(object const& index, T const& x) // insert object before index + { + base::insert(index, object(x)); + } + + object pop() { return base::pop(); } + object pop(ssize_t index) { return base::pop(index); } + + template <class T> + object pop(T const& index) + { + return base::pop(object(index)); + } + + template <class T> + void remove(T const& value) + { + base::remove(object(value)); + } + +#if PY_VERSION_HEX <= 0x03000000 + void sort() { base::sort(); } + + template <class T> + void sort(T const& value) + { + base::sort(object(value)); + } +#endif + + public: // implementation detail -- for internal use only + BOOST_PYTHON_FORWARD_OBJECT_CONSTRUCTORS(list, base) +}; + +// +// Converter Specializations +// +namespace converter +{ + template <> + struct object_manager_traits<list> + : pytype_object_manager_traits<&PyList_Type,list> + { + }; +} + +}} // namespace boost::python + +#endif // LIST_DWA2002627_HPP diff --git a/boost/python/long.hpp b/boost/python/long.hpp new file mode 100644 index 0000000000..129c61f9e4 --- /dev/null +++ b/boost/python/long.hpp @@ -0,0 +1,68 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef LONG_DWA2002627_HPP +# define LONG_DWA2002627_HPP + +# include <boost/python/detail/prefix.hpp> + +# include <boost/python/object.hpp> +# include <boost/python/converter/pytype_object_mgr_traits.hpp> + +namespace boost { namespace python { + +namespace detail +{ + struct BOOST_PYTHON_DECL long_base : object + { + protected: + long_base(); // new long_ + explicit long_base(object_cref rhs); + explicit long_base(object_cref rhs, object_cref base); + + BOOST_PYTHON_FORWARD_OBJECT_CONSTRUCTORS(long_base, object) + + private: + static detail::new_non_null_reference call(object const&); + static detail::new_non_null_reference call(object const&, object const&); + }; +} + +class long_ : public detail::long_base +{ + typedef detail::long_base base; + public: + long_() {} // new long_ + + template <class T> + explicit long_(T const& rhs) + : detail::long_base(object(rhs)) + { + } + + template <class T, class U> + explicit long_(T const& rhs, U const& base) + : detail::long_base(object(rhs), object(base)) + { + } + + public: // implementation detail -- for internal use only + BOOST_PYTHON_FORWARD_OBJECT_CONSTRUCTORS(long_, base) +}; + +// +// Converter Specializations +// +namespace converter +{ + template <> + struct object_manager_traits<long_> + : pytype_object_manager_traits<&PyLong_Type,long_> + { + }; +} + +}} // namespace boost::python + +#endif // LONG_DWA2002627_HPP diff --git a/boost/python/lvalue_from_pytype.hpp b/boost/python/lvalue_from_pytype.hpp new file mode 100644 index 0000000000..e15dfbbb85 --- /dev/null +++ b/boost/python/lvalue_from_pytype.hpp @@ -0,0 +1,116 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef LVALUE_FROM_PYTYPE_DWA2002130_HPP +# define LVALUE_FROM_PYTYPE_DWA2002130_HPP + +# include <boost/python/detail/prefix.hpp> +#ifndef BOOST_PYTHON_NO_PY_SIGNATURES +# include <boost/python/converter/pytype_function.hpp> +#endif + +# include <boost/python/type_id.hpp> +# include <boost/python/converter/registry.hpp> +# include <boost/python/detail/void_ptr.hpp> + +namespace boost { namespace python { + +namespace detail +{ + // Given a pointer-to-function of 1 parameter returning a reference + // type, return the type_id of the function's return type. + template <class T, class U> + inline type_info extractor_type_id(T&(*)(U)) + { + return type_id<T>(); + } + + // A function generator whose static execute() function is an lvalue + // 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 <class Extractor, class U> + struct normalized_extractor + { + static inline void* execute(PyObject* op) + { + typedef typename boost::add_reference<U>::type param; + return &Extractor::execute( + boost::python::detail::void_ptr_to_reference( + op, (param(*)())0 ) + ); + } + }; + + // Given an Extractor type and a pointer to its execute function, + // return a new object whose static execute function does the same + // job but is a conforming lvalue from_python conversion function. + // + // usage: normalize<Extractor>(&Extractor::execute) + template <class Extractor, class T, class U> + inline normalized_extractor<Extractor,U> + normalize(T(*)(U), Extractor* = 0) + { + return normalized_extractor<Extractor, U>(); + } +} + +// An Extractor which extracts the given member from a Python object +// whose instances are stored as InstanceType. +template <class InstanceType, class MemberType, MemberType (InstanceType::*member)> +struct extract_member +{ + static MemberType& execute(InstanceType& c) + { + (void)Py_TYPE(&c); // static assertion + return c.*member; + } +}; + +// An Extractor which simply extracts the entire python object +// instance of InstanceType. +template <class InstanceType> +struct extract_identity +{ + static InstanceType& execute(InstanceType& c) + { + (void)Py_TYPE(&c); // static assertion + return c; + } +}; + +// Registers a from_python conversion which extracts lvalues using +// Extractor's static execute function from Python objects whose type +// object is python_type. +template <class Extractor, PyTypeObject const* python_type> +struct lvalue_from_pytype +{ + lvalue_from_pytype() + { + converter::registry::insert + ( &extract + , detail::extractor_type_id(&Extractor::execute) +#ifndef BOOST_PYTHON_NO_PY_SIGNATURES + , &get_pytype +#endif + ); + } + private: + static void* extract(PyObject* op) + { + return PyObject_TypeCheck(op, const_cast<PyTypeObject*>(python_type)) + ? const_cast<void*>( + static_cast<void const volatile*>( + detail::normalize<Extractor>(&Extractor::execute).execute(op))) + : 0 + ; + } +#ifndef BOOST_PYTHON_NO_PY_SIGNATURES + static PyTypeObject const*get_pytype() { return python_type; } +#endif +}; + +}} // namespace boost::python + +#endif // LVALUE_FROM_PYTYPE_DWA2002130_HPP diff --git a/boost/python/make_constructor.hpp b/boost/python/make_constructor.hpp new file mode 100644 index 0000000000..8ae722bbe3 --- /dev/null +++ b/boost/python/make_constructor.hpp @@ -0,0 +1,290 @@ +// Copyright David Abrahams 2001. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef MAKE_CONSTRUCTOR_DWA20011221_HPP +# define MAKE_CONSTRUCTOR_DWA20011221_HPP + +# include <boost/python/detail/prefix.hpp> + +# include <boost/python/default_call_policies.hpp> +# include <boost/python/args.hpp> +# include <boost/python/object_fwd.hpp> + +# include <boost/python/object/function_object.hpp> +# include <boost/python/object/make_holder.hpp> +# include <boost/python/object/pointer_holder.hpp> +# include <boost/python/converter/context_result_converter.hpp> + +# include <boost/python/detail/caller.hpp> +# include <boost/python/detail/none.hpp> + +# include <boost/mpl/size.hpp> +# include <boost/mpl/int.hpp> +# include <boost/mpl/push_front.hpp> +# include <boost/mpl/pop_front.hpp> +# include <boost/mpl/assert.hpp> + +namespace boost { namespace python { + +namespace detail +{ + template <class T> + struct install_holder : converter::context_result_converter + { + install_holder(PyObject* args_) + : m_self(PyTuple_GetItem(args_, 0)) {} + + PyObject* operator()(T x) const + { + dispatch(x, is_pointer<T>()); + return none(); + } + + private: + template <class U> + void dispatch(U* x, mpl::true_) const + { + std::auto_ptr<U> owner(x); + dispatch(owner, mpl::false_()); + } + + template <class Ptr> + void dispatch(Ptr x, mpl::false_) const + { + typedef typename pointee<Ptr>::type value_type; + typedef objects::pointer_holder<Ptr,value_type> holder; + typedef objects::instance<holder> instance_t; + + void* memory = holder::allocate(this->m_self, offsetof(instance_t, storage), sizeof(holder)); + try { + (new (memory) holder(x))->install(this->m_self); + } + catch(...) { + holder::deallocate(this->m_self, memory); + throw; + } + } + + PyObject* m_self; + }; + + struct constructor_result_converter + { + template <class T> + struct apply + { + typedef install_holder<T> type; + }; + }; + + template <class BaseArgs, class Offset> + struct offset_args + { + offset_args(BaseArgs base_) : base(base_) {} + BaseArgs base; + }; + + template <int N, class BaseArgs, class Offset> + inline PyObject* get(mpl::int_<N>, offset_args<BaseArgs,Offset> const& args_) + { + return get(mpl::int_<(N+Offset::value)>(), args_.base); + } + + template <class BaseArgs, class Offset> + inline unsigned arity(offset_args<BaseArgs,Offset> const& args_) + { + return arity(args_.base) - Offset::value; + } + + template <class BasePolicy_ = default_call_policies> + struct constructor_policy : BasePolicy_ + { + constructor_policy(BasePolicy_ base) : BasePolicy_(base) {} + + // If the BasePolicy_ supplied a result converter it would be + // ignored; issue an error if it's not the default. +#if defined _MSC_VER && _MSC_VER < 1300 + typedef is_same< + typename BasePolicy_::result_converter + , default_result_converter + > same_result_converter; + //see above for explanation + BOOST_STATIC_ASSERT(same_result_converter::value) ; +#else + BOOST_MPL_ASSERT_MSG( + (is_same< + typename BasePolicy_::result_converter + , default_result_converter + >::value) + , MAKE_CONSTRUCTOR_SUPPLIES_ITS_OWN_RESULT_CONVERTER_THAT_WOULD_OVERRIDE_YOURS + , (typename BasePolicy_::result_converter) + ); +#endif + typedef constructor_result_converter result_converter; + typedef offset_args<typename BasePolicy_::argument_package, mpl::int_<1> > argument_package; + }; + + template <class InnerSignature> + struct outer_constructor_signature + { + typedef typename mpl::pop_front<InnerSignature>::type inner_args; + typedef typename mpl::push_front<inner_args,object>::type outer_args; + typedef typename mpl::push_front<outer_args,void>::type type; + }; + + // ETI workaround + template <> + struct outer_constructor_signature<int> + { + typedef int type; + }; + + // + // These helper functions for make_constructor (below) do the raw work + // of constructing a Python object from some invokable entity. See + // <boost/python/detail/caller.hpp> for more information about how + // the Sig arguments is used. + // + // @group make_constructor_aux { + template <class F, class CallPolicies, class Sig> + object make_constructor_aux( + F f // An object that can be invoked by detail::invoke() + , CallPolicies const& p // CallPolicies to use in the invocation + , Sig const& // An MPL sequence of argument types expected by F + ) + { + typedef typename outer_constructor_signature<Sig>::type outer_signature; + + typedef constructor_policy<CallPolicies> inner_policy; + + return objects::function_object( + objects::py_function( + detail::caller<F,inner_policy,Sig>(f, inner_policy(p)) + , outer_signature() + ) + ); + } + + // As above, except that it accepts argument keywords. NumKeywords + // is used only for a compile-time assertion to make sure the user + // doesn't pass more keywords than the function can accept. To + // disable all checking, pass mpl::int_<0> for NumKeywords. + template <class F, class CallPolicies, class Sig, class NumKeywords> + object make_constructor_aux( + F f + , CallPolicies const& p + , Sig const& + , detail::keyword_range const& kw // a [begin,end) pair of iterators over keyword names + , NumKeywords // An MPL integral type wrapper: the size of kw + ) + { + enum { arity = mpl::size<Sig>::value - 1 }; + + typedef typename detail::error::more_keywords_than_function_arguments< + NumKeywords::value, arity + >::too_many_keywords assertion; + + typedef typename outer_constructor_signature<Sig>::type outer_signature; + + typedef constructor_policy<CallPolicies> inner_policy; + + return objects::function_object( + objects::py_function( + detail::caller<F,inner_policy,Sig>(f, inner_policy(p)) + , outer_signature() + ) + , kw + ); + } + // } + + // + // These dispatch functions are used to discriminate between the + // cases when the 3rd argument is keywords or when it is a + // signature. + // + // @group Helpers for make_constructor when called with 3 arguments. { + // + template <class F, class CallPolicies, class Keywords> + object make_constructor_dispatch(F f, CallPolicies const& policies, Keywords const& kw, mpl::true_) + { + return detail::make_constructor_aux( + f + , policies + , detail::get_signature(f) + , kw.range() + , mpl::int_<Keywords::size>() + ); + } + + template <class F, class CallPolicies, class Signature> + object make_constructor_dispatch(F f, CallPolicies const& policies, Signature const& sig, mpl::false_) + { + return detail::make_constructor_aux( + f + , policies + , sig + ); + } + // } +} + +// These overloaded functions wrap a function or member function +// pointer as a Python object, using optional CallPolicies, +// Keywords, and/or Signature. @group { +// +template <class F> +object make_constructor(F f) +{ + return detail::make_constructor_aux( + f,default_call_policies(), detail::get_signature(f)); +} + +template <class F, class CallPolicies> +object make_constructor(F f, CallPolicies const& policies) +{ + return detail::make_constructor_aux( + f, policies, detail::get_signature(f)); +} + +template <class F, class CallPolicies, class KeywordsOrSignature> +object make_constructor( + F f + , CallPolicies const& policies + , KeywordsOrSignature const& keywords_or_signature) +{ + typedef typename + detail::is_reference_to_keywords<KeywordsOrSignature&>::type + is_kw; + + return detail::make_constructor_dispatch( + f + , policies + , keywords_or_signature + , is_kw() + ); +} + +template <class F, class CallPolicies, class Keywords, class Signature> +object make_constructor( + F f + , CallPolicies const& policies + , Keywords const& kw + , Signature const& sig + ) +{ + return detail::make_constructor_aux( + f + , policies + , sig + , kw.range() + , mpl::int_<Keywords::size>() + ); +} +// } + +}} + + +#endif // MAKE_CONSTRUCTOR_DWA20011221_HPP diff --git a/boost/python/make_function.hpp b/boost/python/make_function.hpp new file mode 100644 index 0000000000..f2f2a9e545 --- /dev/null +++ b/boost/python/make_function.hpp @@ -0,0 +1,153 @@ +// Copyright David Abrahams 2001. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef MAKE_FUNCTION_DWA20011221_HPP +# define MAKE_FUNCTION_DWA20011221_HPP + +# include <boost/python/detail/prefix.hpp> + +# include <boost/python/default_call_policies.hpp> +# include <boost/python/args.hpp> +# include <boost/python/detail/caller.hpp> + +# include <boost/python/object/function_object.hpp> + +# include <boost/mpl/size.hpp> +# include <boost/mpl/int.hpp> + +namespace boost { namespace python { + +namespace detail +{ + // make_function_aux -- + // + // These helper functions for make_function (below) do the raw work + // of constructing a Python object from some invokable entity. See + // <boost/python/detail/caller.hpp> for more information about how + // the Sig arguments is used. + template <class F, class CallPolicies, class Sig> + object make_function_aux( + F f // An object that can be invoked by detail::invoke() + , CallPolicies const& p // CallPolicies to use in the invocation + , Sig const& // An MPL sequence of argument types expected by F + ) + { + return objects::function_object( + detail::caller<F,CallPolicies,Sig>(f, p) + ); + } + + // As above, except that it accepts argument keywords. NumKeywords + // is used only for a compile-time assertion to make sure the user + // doesn't pass more keywords than the function can accept. To + // disable all checking, pass mpl::int_<0> for NumKeywords. + template <class F, class CallPolicies, class Sig, class NumKeywords> + object make_function_aux( + F f + , CallPolicies const& p + , Sig const& + , detail::keyword_range const& kw // a [begin,end) pair of iterators over keyword names + , NumKeywords // An MPL integral type wrapper: the size of kw + ) + { + enum { arity = mpl::size<Sig>::value - 1 }; + + typedef typename detail::error::more_keywords_than_function_arguments< + NumKeywords::value, arity + >::too_many_keywords assertion; + + return objects::function_object( + detail::caller<F,CallPolicies,Sig>(f, p) + , kw); + } + + // Helpers for make_function when called with 3 arguments. These + // dispatch functions are used to discriminate between the cases + // when the 3rd argument is keywords or when it is a signature. + // + // @group { + template <class F, class CallPolicies, class Keywords> + object make_function_dispatch(F f, CallPolicies const& policies, Keywords const& kw, mpl::true_) + { + return detail::make_function_aux( + f + , policies + , detail::get_signature(f) + , kw.range() + , mpl::int_<Keywords::size>() + ); + } + + template <class F, class CallPolicies, class Signature> + object make_function_dispatch(F f, CallPolicies const& policies, Signature const& sig, mpl::false_) + { + return detail::make_function_aux( + f + , policies + , sig + ); + } + // } + + } + +// These overloaded functions wrap a function or member function +// pointer as a Python object, using optional CallPolicies, +// Keywords, and/or Signature. +// +// @group { +template <class F> +object make_function(F f) +{ + return detail::make_function_aux( + f,default_call_policies(), detail::get_signature(f)); +} + +template <class F, class CallPolicies> +object make_function(F f, CallPolicies const& policies) +{ + return detail::make_function_aux( + f, policies, detail::get_signature(f)); +} + +template <class F, class CallPolicies, class KeywordsOrSignature> +object make_function( + F f + , CallPolicies const& policies + , KeywordsOrSignature const& keywords_or_signature) +{ + typedef typename + detail::is_reference_to_keywords<KeywordsOrSignature&>::type + is_kw; + + return detail::make_function_dispatch( + f + , policies + , keywords_or_signature + , is_kw() + ); +} + +template <class F, class CallPolicies, class Keywords, class Signature> +object make_function( + F f + , CallPolicies const& policies + , Keywords const& kw + , Signature const& sig + ) +{ + return detail::make_function_aux( + f + , policies + , sig + , kw.range() + , mpl::int_<Keywords::size>() + ); +} +// } + +}} + + +#endif // MAKE_FUNCTION_DWA20011221_HPP diff --git a/boost/python/manage_new_object.hpp b/boost/python/manage_new_object.hpp new file mode 100644 index 0000000000..d81421dace --- /dev/null +++ b/boost/python/manage_new_object.hpp @@ -0,0 +1,41 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef MANAGE_NEW_OBJECT_DWA200222_HPP +# define MANAGE_NEW_OBJECT_DWA200222_HPP + +# include <boost/python/detail/prefix.hpp> +# include <boost/python/detail/indirect_traits.hpp> +# include <boost/mpl/if.hpp> +# include <boost/python/to_python_indirect.hpp> +# include <boost/type_traits/composite_traits.hpp> + +namespace boost { namespace python { + +namespace detail +{ + template <class R> + struct manage_new_object_requires_a_pointer_return_type +# if defined(__GNUC__) && __GNUC__ >= 3 || defined(__EDG__) + {} +# endif + ; +} + +struct manage_new_object +{ + template <class T> + struct apply + { + typedef typename mpl::if_c< + boost::is_pointer<T>::value + , to_python_indirect<T, detail::make_owning_holder> + , detail::manage_new_object_requires_a_pointer_return_type<T> + >::type type; + }; +}; + +}} // namespace boost::python + +#endif // MANAGE_NEW_OBJECT_DWA200222_HPP diff --git a/boost/python/module.hpp b/boost/python/module.hpp new file mode 100644 index 0000000000..8ad69f5a34 --- /dev/null +++ b/boost/python/module.hpp @@ -0,0 +1,13 @@ +// Copyright David Abrahams 2001. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef MODULE_DWA2001128_HPP +# define MODULE_DWA2001128_HPP + +# include <boost/python/detail/prefix.hpp> + +# include <boost/python/module_init.hpp> +# define BOOST_PYTHON_MODULE BOOST_PYTHON_MODULE_INIT + +#endif // MODULE_DWA20011221_HPP diff --git a/boost/python/module_init.hpp b/boost/python/module_init.hpp new file mode 100644 index 0000000000..54d87e4b41 --- /dev/null +++ b/boost/python/module_init.hpp @@ -0,0 +1,91 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef MODULE_INIT_DWA20020722_HPP +# define MODULE_INIT_DWA20020722_HPP + +# include <boost/python/detail/prefix.hpp> +# include <boost/preprocessor/cat.hpp> +# include <boost/preprocessor/stringize.hpp> + +# ifndef BOOST_PYTHON_MODULE_INIT + +namespace boost { namespace python { namespace detail { + +# if PY_VERSION_HEX >= 0x03000000 + +BOOST_PYTHON_DECL PyObject* init_module(PyModuleDef&, void(*)()); + +#else + +BOOST_PYTHON_DECL PyObject* init_module(char const* name, void(*)()); + +#endif + +}}} + +# if PY_VERSION_HEX >= 0x03000000 + +# define _BOOST_PYTHON_MODULE_INIT(name) \ + PyObject* BOOST_PP_CAT(PyInit_, name)() \ + { \ + static PyModuleDef_Base initial_m_base = { \ + PyObject_HEAD_INIT(NULL) \ + 0, /* m_init */ \ + 0, /* m_index */ \ + 0 /* m_copy */ }; \ + static PyMethodDef initial_methods[] = { { 0, 0, 0, 0 } }; \ + \ + static struct PyModuleDef moduledef = { \ + initial_m_base, \ + BOOST_PP_STRINGIZE(name), \ + 0, /* m_doc */ \ + -1, /* m_size */ \ + initial_methods, \ + 0, /* m_reload */ \ + 0, /* m_traverse */ \ + 0, /* m_clear */ \ + 0, /* m_free */ \ + }; \ + \ + return boost::python::detail::init_module( \ + moduledef, BOOST_PP_CAT(init_module_, name) ); \ + } \ + void BOOST_PP_CAT(init_module_, name)() + +# else + +# define _BOOST_PYTHON_MODULE_INIT(name) \ + void BOOST_PP_CAT(init,name)() \ +{ \ + boost::python::detail::init_module( \ + BOOST_PP_STRINGIZE(name),&BOOST_PP_CAT(init_module_,name)); \ +} \ + void BOOST_PP_CAT(init_module_,name)() + +# endif + +# if (defined(_WIN32) || defined(__CYGWIN__)) && !defined(BOOST_PYTHON_STATIC_MODULE) + +# define BOOST_PYTHON_MODULE_INIT(name) \ + void BOOST_PP_CAT(init_module_,name)(); \ +extern "C" __declspec(dllexport) _BOOST_PYTHON_MODULE_INIT(name) + +# elif BOOST_PYTHON_USE_GCC_SYMBOL_VISIBILITY + +# define BOOST_PYTHON_MODULE_INIT(name) \ + void BOOST_PP_CAT(init_module_,name)(); \ +extern "C" __attribute__ ((visibility("default"))) _BOOST_PYTHON_MODULE_INIT(name) + +# else + +# define BOOST_PYTHON_MODULE_INIT(name) \ + void BOOST_PP_CAT(init_module_,name)(); \ +extern "C" _BOOST_PYTHON_MODULE_INIT(name) + +# endif + +# endif + +#endif // MODULE_INIT_DWA20020722_HPP diff --git a/boost/python/numeric.hpp b/boost/python/numeric.hpp new file mode 100644 index 0000000000..ab4db8c32e --- /dev/null +++ b/boost/python/numeric.hpp @@ -0,0 +1,242 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef NUMARRAY_DWA2002922_HPP +# define NUMARRAY_DWA2002922_HPP + +# include <boost/python/detail/prefix.hpp> + +# include <boost/python/tuple.hpp> +# include <boost/python/str.hpp> +# include <boost/preprocessor/iteration/local.hpp> +# include <boost/preprocessor/cat.hpp> +# include <boost/preprocessor/repetition/enum.hpp> +# include <boost/preprocessor/repetition/enum_params.hpp> +# include <boost/preprocessor/repetition/enum_binary_params.hpp> + +namespace boost { namespace python { namespace numeric { + +class array; + +namespace aux +{ + struct BOOST_PYTHON_DECL array_base : object + { +# define BOOST_PP_LOCAL_MACRO(n) \ + array_base(BOOST_PP_ENUM_PARAMS_Z(1, n, object const& x)); +# define BOOST_PP_LOCAL_LIMITS (1, 7) +# include BOOST_PP_LOCAL_ITERATE() + + object argmax(long axis=-1); + object argmin(long axis=-1); + object argsort(long axis=-1); + object astype(object const& type = object()); + void byteswap(); + object copy() const; + object diagonal(long offset = 0, long axis1 = 0, long axis2 = 1) const; + void info() const; + bool is_c_array() const; + bool isbyteswapped() const; + array new_(object type) const; + void sort(); + object trace(long offset = 0, long axis1 = 0, long axis2 = 1) const; + object type() const; + char typecode() const; + + object factory( + object const& sequence = object() + , object const& typecode = object() + , bool copy = true + , bool savespace = false + , object type = object() + , object shape = object()); + + object getflat() const; + long getrank() const; + object getshape() const; + bool isaligned() const; + bool iscontiguous() const; + long itemsize() const; + long nelements() const; + object nonzero() const; + + void put(object const& indices, object const& values); + + void ravel(); + + object repeat(object const& repeats, long axis=0); + + void resize(object const& shape); + + void setflat(object const& flat); + void setshape(object const& shape); + + void swapaxes(long axis1, long axis2); + + object take(object const& sequence, long axis = 0) const; + + void tofile(object const& file) const; + + str tostring() const; + + void transpose(object const& axes = object()); + + object view() const; + + public: // implementation detail - do not touch. + BOOST_PYTHON_FORWARD_OBJECT_CONSTRUCTORS(array_base, object); + }; + + struct BOOST_PYTHON_DECL array_object_manager_traits + { + static bool check(PyObject* obj); + static detail::new_non_null_reference adopt(PyObject* obj); + static PyTypeObject const* get_pytype() ; + }; +} // namespace aux + +class array : public aux::array_base +{ + typedef aux::array_base base; + public: + + object astype() { return base::astype(); } + + template <class Type> + object astype(Type const& type_) + { + return base::astype(object(type_)); + } + + template <class Type> + array new_(Type const& type_) const + { + return base::new_(object(type_)); + } + + template <class Sequence> + void resize(Sequence const& x) + { + base::resize(object(x)); + } + +# define BOOST_PP_LOCAL_MACRO(n) \ + void resize(BOOST_PP_ENUM_PARAMS_Z(1, n, long x)) \ + { \ + resize(make_tuple(BOOST_PP_ENUM_PARAMS_Z(1, n, x))); \ + } +# define BOOST_PP_LOCAL_LIMITS (1, BOOST_PYTHON_MAX_ARITY) +# include BOOST_PP_LOCAL_ITERATE() + + template <class Sequence> + void setshape(Sequence const& x) + { + base::setshape(object(x)); + } + +# define BOOST_PP_LOCAL_MACRO(n) \ + void setshape(BOOST_PP_ENUM_PARAMS_Z(1, n, long x)) \ + { \ + setshape(make_tuple(BOOST_PP_ENUM_PARAMS_Z(1, n, x))); \ + } +# define BOOST_PP_LOCAL_LIMITS (1, BOOST_PYTHON_MAX_ARITY) +# include BOOST_PP_LOCAL_ITERATE() + + template <class Indices, class Values> + void put(Indices const& indices, Values const& values) + { + base::put(object(indices), object(values)); + } + + template <class Sequence> + object take(Sequence const& sequence, long axis = 0) + { + return base::take(object(sequence), axis); + } + + template <class File> + void tofile(File const& f) const + { + base::tofile(object(f)); + } + + object factory() + { + return base::factory(); + } + + template <class Sequence> + object factory(Sequence const& sequence) + { + return base::factory(object(sequence)); + } + + template <class Sequence, class Typecode> + object factory( + Sequence const& sequence + , Typecode const& typecode_ + , bool copy = true + , bool savespace = false + ) + { + return base::factory(object(sequence), object(typecode_), copy, savespace); + } + + template <class Sequence, class Typecode, class Type> + object factory( + Sequence const& sequence + , Typecode const& typecode_ + , bool copy + , bool savespace + , Type const& type + ) + { + return base::factory(object(sequence), object(typecode_), copy, savespace, object(type)); + } + + template <class Sequence, class Typecode, class Type, class Shape> + object factory( + Sequence const& sequence + , Typecode const& typecode_ + , bool copy + , bool savespace + , Type const& type + , Shape const& shape + ) + { + return base::factory(object(sequence), object(typecode_), copy, savespace, object(type), object(shape)); + } + +# define BOOST_PYTHON_ENUM_AS_OBJECT(z, n, x) object(BOOST_PP_CAT(x,n)) +# define BOOST_PP_LOCAL_MACRO(n) \ + template <BOOST_PP_ENUM_PARAMS_Z(1, n, class T)> \ + explicit array(BOOST_PP_ENUM_BINARY_PARAMS_Z(1, n, T, const& x)) \ + : base(BOOST_PP_ENUM_1(n, BOOST_PYTHON_ENUM_AS_OBJECT, x)) \ + {} +# define BOOST_PP_LOCAL_LIMITS (1, 7) +# include BOOST_PP_LOCAL_ITERATE() +# undef BOOST_PYTHON_AS_OBJECT + + static BOOST_PYTHON_DECL void set_module_and_type(char const* package_name = 0, char const* type_attribute_name = 0); + static BOOST_PYTHON_DECL std::string get_module_name(); + + public: // implementation detail -- for internal use only + BOOST_PYTHON_FORWARD_OBJECT_CONSTRUCTORS(array, base); +}; + +} // namespace boost::python::numeric + +namespace converter +{ + template <> + struct object_manager_traits< numeric::array > + : numeric::aux::array_object_manager_traits + { + BOOST_STATIC_CONSTANT(bool, is_specialized = true); + }; +} + +}} // namespace boost::python + +#endif // NUMARRAY_DWA2002922_HPP diff --git a/boost/python/object.hpp b/boost/python/object.hpp new file mode 100644 index 0000000000..9adec90f64 --- /dev/null +++ b/boost/python/object.hpp @@ -0,0 +1,27 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef OBJECT_DWA2002612_HPP +# define OBJECT_DWA2002612_HPP + +# include <boost/python/ssize_t.hpp> +# include <boost/python/object_core.hpp> +# include <boost/python/object_attributes.hpp> +# include <boost/python/object_items.hpp> +# include <boost/python/object_slices.hpp> +# include <boost/python/object_operators.hpp> +# include <boost/python/converter/arg_to_python.hpp> + +namespace boost { namespace python { + + inline ssize_t len(object const& obj) + { + ssize_t result = PyObject_Length(obj.ptr()); + if (PyErr_Occurred()) throw_error_already_set(); + return result; + } + +}} // namespace boost::python + +#endif // OBJECT_DWA2002612_HPP diff --git a/boost/python/object/add_to_namespace.hpp b/boost/python/object/add_to_namespace.hpp new file mode 100644 index 0000000000..9f4167d6d2 --- /dev/null +++ b/boost/python/object/add_to_namespace.hpp @@ -0,0 +1,23 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef ADD_TO_NAMESPACE_DWA200286_HPP +# define ADD_TO_NAMESPACE_DWA200286_HPP + +# include <boost/python/object_fwd.hpp> + +namespace boost { namespace python { namespace objects { + +// +// A setattr that's "smart" about function overloading (and docstrings). +// +BOOST_PYTHON_DECL void add_to_namespace( + object const& name_space, char const* name, object const& attribute); + +BOOST_PYTHON_DECL void add_to_namespace( + object const& name_space, char const* name, object const& attribute, char const* doc); + +}}} // namespace boost::python::objects + +#endif // ADD_TO_NAMESPACE_DWA200286_HPP diff --git a/boost/python/object/class.hpp b/boost/python/object/class.hpp new file mode 100644 index 0000000000..6aad45e786 --- /dev/null +++ b/boost/python/object/class.hpp @@ -0,0 +1,64 @@ +// Copyright David Abrahams 2001. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef CLASS_DWA20011214_HPP +# define CLASS_DWA20011214_HPP + +# include <boost/python/detail/prefix.hpp> +# include <boost/utility.hpp> +# include <boost/python/object_core.hpp> +# include <boost/python/type_id.hpp> +# include <cstddef> + +namespace boost { namespace python { + +namespace objects { + +struct BOOST_PYTHON_DECL class_base : python::api::object +{ + // constructor + class_base( + char const* name // The name of the class + + , std::size_t num_types // A list of class_ids. The first is the type + , type_info const*const types // this is wrapping. The rest are the types of + // any bases. + + , char const* doc = 0 // Docstring, if any. + ); + + + // Implementation detail. Hiding this in the private section would + // require use of template friend declarations. + void enable_pickling_(bool getstate_manages_dict); + + protected: + void add_property( + char const* name, object const& fget, char const* docstr); + void add_property(char const* name, + object const& fget, object const& fset, char const* docstr); + + void add_static_property(char const* name, object const& fget); + void add_static_property(char const* name, object const& fget, object const& fset); + + // Retrieve the underlying object + void setattr(char const* name, object const&); + + // Set a special attribute in the class which tells Boost.Python + // to allocate extra bytes for embedded C++ objects in Python + // instances. + void set_instance_size(std::size_t bytes); + + // Set an __init__ function which throws an appropriate exception + // for abstract classes. + void def_no_init(); + + // Effects: + // setattr(self, staticmethod(getattr(self, method_name))) + void make_method_static(const char *method_name); +}; + +}}} // namespace boost::python::objects + +#endif // CLASS_DWA20011214_HPP diff --git a/boost/python/object/class_detail.hpp b/boost/python/object/class_detail.hpp new file mode 100644 index 0000000000..a17a4f4330 --- /dev/null +++ b/boost/python/object/class_detail.hpp @@ -0,0 +1,19 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef CLASS_DETAIL_DWA200295_HPP +# define CLASS_DETAIL_DWA200295_HPP + +# include <boost/python/handle.hpp> +# include <boost/python/type_id.hpp> + +namespace boost { namespace python { namespace objects { + +BOOST_PYTHON_DECL type_handle registered_class_object(type_info id); +BOOST_PYTHON_DECL type_handle class_metatype(); +BOOST_PYTHON_DECL type_handle class_type(); + +}}} // namespace boost::python::object + +#endif // CLASS_DETAIL_DWA200295_HPP diff --git a/boost/python/object/class_metadata.hpp b/boost/python/object/class_metadata.hpp new file mode 100644 index 0000000000..155ae35d06 --- /dev/null +++ b/boost/python/object/class_metadata.hpp @@ -0,0 +1,297 @@ +// Copyright David Abrahams 2004. Distributed under the Boost +// Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +#ifndef CLASS_METADATA_DWA2004719_HPP +# define CLASS_METADATA_DWA2004719_HPP +# include <boost/python/converter/shared_ptr_from_python.hpp> + +# include <boost/python/object/inheritance.hpp> +# include <boost/python/object/class_wrapper.hpp> +# include <boost/python/object/make_instance.hpp> +# include <boost/python/object/value_holder.hpp> +# include <boost/python/object/pointer_holder.hpp> +# include <boost/python/object/make_ptr_instance.hpp> + +# include <boost/python/detail/force_instantiate.hpp> +# include <boost/python/detail/not_specified.hpp> + +# include <boost/python/has_back_reference.hpp> +# include <boost/python/bases.hpp> + +# include <boost/type_traits/add_pointer.hpp> +# include <boost/type_traits/is_convertible.hpp> +# include <boost/type_traits/is_polymorphic.hpp> + +# include <boost/mpl/if.hpp> +# include <boost/mpl/eval_if.hpp> +# include <boost/mpl/bool.hpp> +# include <boost/mpl/or.hpp> +# include <boost/mpl/identity.hpp> +# include <boost/mpl/for_each.hpp> +# include <boost/mpl/placeholders.hpp> +# include <boost/mpl/single_view.hpp> + +# include <boost/mpl/assert.hpp> +# include <boost/type_traits/is_same.hpp> + +# include <boost/type_traits/is_convertible.hpp> + +# include <boost/noncopyable.hpp> +# include <boost/detail/workaround.hpp> + +namespace boost { namespace python { namespace objects { + +BOOST_PYTHON_DECL +void copy_class_object(type_info const& src, type_info const& dst); + +// +// Support for registering base/derived relationships +// +template <class Derived> +struct register_base_of +{ + template <class Base> + inline void operator()(Base*) const + { +# if !BOOST_WORKAROUND(BOOST_MSVC, == 1200) + BOOST_MPL_ASSERT_NOT((is_same<Base,Derived>)); +# else + BOOST_STATIC_ASSERT(!(is_same<Base,Derived>::value)); +# endif + + // Register the Base class + register_dynamic_id<Base>(); + + // Register the up-cast + register_conversion<Derived,Base>(false); + + // Register the down-cast, if appropriate. + this->register_downcast((Base*)0, is_polymorphic<Base>()); + } + + private: + static inline void register_downcast(void*, mpl::false_) {} + + template <class Base> + static inline void register_downcast(Base*, mpl::true_) + { + register_conversion<Base, Derived>(true); + } + +}; + +// +// Preamble of register_class. Also used for callback classes, which +// need some registration of their own. +// +template <class T, class Bases> +inline void register_shared_ptr_from_python_and_casts(T*, Bases) +{ + // Constructor performs registration + python::detail::force_instantiate(converter::shared_ptr_from_python<T>()); + + // + // register all up/downcasts here. We're using the alternate + // interface to mpl::for_each to avoid an MSVC 6 bug. + // + register_dynamic_id<T>(); + mpl::for_each(register_base_of<T>(), (Bases*)0, (add_pointer<mpl::_>*)0); +} + +// +// Helper for choosing the unnamed held_type argument +// +template <class T, class Prev> +struct select_held_type + : mpl::if_< + mpl::or_< + python::detail::specifies_bases<T> + , is_same<T,noncopyable> + > + , Prev + , T + > +{ +}; + +template < + class T // class being wrapped + , class X1 // = detail::not_specified + , class X2 // = detail::not_specified + , class X3 // = detail::not_specified +> +struct class_metadata +{ + // + // Calculate the unnamed template arguments + // + + // held_type_arg -- not_specified, [a class derived from] T or a + // smart pointer to [a class derived from] T. Preserving + // not_specified allows us to give class_<T,T> a back-reference. + typedef typename select_held_type< + X1 + , typename select_held_type< + X2 + , typename select_held_type< + X3 + , python::detail::not_specified + >::type + >::type + >::type held_type_arg; + + // bases + typedef typename python::detail::select_bases< + X1 + , typename python::detail::select_bases< + X2 + , typename python::detail::select_bases< + X3 + , python::bases<> + >::type + >::type + >::type bases; + + typedef mpl::or_< + is_same<X1,noncopyable> + , is_same<X2,noncopyable> + , is_same<X3,noncopyable> + > is_noncopyable; + + // + // Holder computation. + // + + // Compute the actual type that will be held in the Holder. + typedef typename mpl::if_< + is_same<held_type_arg,python::detail::not_specified>, T, held_type_arg + >::type held_type; + + // Determine if the object will be held by value + typedef is_convertible<held_type*,T*> use_value_holder; + + // Compute the "wrapped type", that is, if held_type is a smart + // pointer, we're talking about the pointee. + typedef typename mpl::eval_if< + use_value_holder + , mpl::identity<held_type> + , pointee<held_type> + >::type wrapped; + + // Determine whether to use a "back-reference holder" + typedef mpl::or_< + has_back_reference<T> + , is_same<held_type_arg,T> + , is_base_and_derived<T,wrapped> + > use_back_reference; + + // Select the holder. + typedef typename mpl::eval_if< + use_back_reference + , mpl::if_< + use_value_holder + , value_holder_back_reference<T, wrapped> + , pointer_holder_back_reference<held_type,T> + > + , mpl::if_< + use_value_holder + , value_holder<T> + , pointer_holder<held_type,wrapped> + > + >::type holder; + + inline static void register_() // Register the runtime metadata. + { + class_metadata::register_aux((T*)0); + } + + private: + template <class T2> + inline static void register_aux(python::wrapper<T2>*) + { + typedef typename mpl::not_<is_same<T2,wrapped> >::type use_callback; + class_metadata::register_aux2((T2*)0, use_callback()); + } + + inline static void register_aux(void*) + { + typedef typename is_base_and_derived<T,wrapped>::type use_callback; + class_metadata::register_aux2((T*)0, use_callback()); + } + + template <class T2, class Callback> + inline static void register_aux2(T2*, Callback) + { + objects::register_shared_ptr_from_python_and_casts((T2*)0, bases()); + + class_metadata::maybe_register_callback_class((T2*)0, Callback()); + + class_metadata::maybe_register_class_to_python((T2*)0, is_noncopyable()); + + class_metadata::maybe_register_pointer_to_python( + (T2*)0, (use_value_holder*)0, (use_back_reference*)0); + } + + + // + // Support for converting smart pointers to python + // + inline static void maybe_register_pointer_to_python(...) {} + +#ifndef BOOST_PYTHON_NO_PY_SIGNATURES + inline static void maybe_register_pointer_to_python(void*,void*,mpl::true_*) + { + objects::copy_class_object(python::type_id<T>(), python::type_id<back_reference<T const &> >()); + objects::copy_class_object(python::type_id<T>(), python::type_id<back_reference<T &> >()); + } +#endif + + template <class T2> + inline static void maybe_register_pointer_to_python(T2*, mpl::false_*, mpl::false_*) + { + python::detail::force_instantiate( + objects::class_value_wrapper< + held_type + , make_ptr_instance<T2, pointer_holder<held_type, T2> > + >() + ); +#ifndef BOOST_PYTHON_NO_PY_SIGNATURES + // explicit qualification of type_id makes msvc6 happy + objects::copy_class_object(python::type_id<T2>(), python::type_id<held_type>()); +#endif + } + // + // Support for registering to-python converters + // + inline static void maybe_register_class_to_python(void*, mpl::true_) {} + + + template <class T2> + inline static void maybe_register_class_to_python(T2*, mpl::false_) + { + python::detail::force_instantiate(class_cref_wrapper<T2, make_instance<T2, holder> >()); +#ifndef BOOST_PYTHON_NO_PY_SIGNATURES + // explicit qualification of type_id makes msvc6 happy + objects::copy_class_object(python::type_id<T2>(), python::type_id<held_type>()); +#endif + } + + // + // Support for registering callback classes + // + inline static void maybe_register_callback_class(void*, mpl::false_) {} + + template <class T2> + inline static void maybe_register_callback_class(T2*, mpl::true_) + { + objects::register_shared_ptr_from_python_and_casts( + (wrapped*)0, mpl::single_view<T2>()); + + // explicit qualification of type_id makes msvc6 happy + objects::copy_class_object(python::type_id<T2>(), python::type_id<wrapped>()); + } +}; + +}}} // namespace boost::python::object + +#endif // CLASS_METADATA_DWA2004719_HPP diff --git a/boost/python/object/class_wrapper.hpp b/boost/python/object/class_wrapper.hpp new file mode 100644 index 0000000000..ffee7457ab --- /dev/null +++ b/boost/python/object/class_wrapper.hpp @@ -0,0 +1,51 @@ +// Copyright David Abrahams 2001. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef CLASS_WRAPPER_DWA20011221_HPP +# define CLASS_WRAPPER_DWA20011221_HPP + +# include <boost/python/to_python_converter.hpp> +#ifndef BOOST_PYTHON_NO_PY_SIGNATURES +# include <boost/python/converter/pytype_function.hpp> +#endif +# include <boost/ref.hpp> + +namespace boost { namespace python { namespace objects { + +// +// These two classes adapt the static execute function of a class +// MakeInstance execute() function returning a new PyObject* +// reference. The first one is used for class copy constructors, and +// the second one is used to handle smart pointers. +// + +template <class Src, class MakeInstance> +struct class_cref_wrapper + : to_python_converter<Src,class_cref_wrapper<Src,MakeInstance> ,true> +{ + static PyObject* convert(Src const& x) + { + return MakeInstance::execute(boost::ref(x)); + } +#ifndef BOOST_PYTHON_NO_PY_SIGNATURES + static PyTypeObject const *get_pytype() { return converter::registered_pytype_direct<Src>::get_pytype(); } +#endif +}; + +template <class Src, class MakeInstance> +struct class_value_wrapper + : to_python_converter<Src,class_value_wrapper<Src,MakeInstance> ,true> +{ + static PyObject* convert(Src x) + { + return MakeInstance::execute(x); + } +#ifndef BOOST_PYTHON_NO_PY_SIGNATURES + static PyTypeObject const *get_pytype() { return MakeInstance::get_pytype(); } +#endif +}; + +}}} // namespace boost::python::objects + +#endif // CLASS_WRAPPER_DWA20011221_HPP diff --git a/boost/python/object/enum_base.hpp b/boost/python/object/enum_base.hpp new file mode 100644 index 0000000000..be34274226 --- /dev/null +++ b/boost/python/object/enum_base.hpp @@ -0,0 +1,36 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef ENUM_BASE_DWA200298_HPP +# define ENUM_BASE_DWA200298_HPP + +# include <boost/python/object_core.hpp> +# include <boost/python/type_id.hpp> +# include <boost/python/converter/to_python_function_type.hpp> +# include <boost/python/converter/convertible_function.hpp> +# include <boost/python/converter/constructor_function.hpp> + +namespace boost { namespace python { namespace objects { + +struct BOOST_PYTHON_DECL enum_base : python::api::object +{ + protected: + enum_base( + char const* name + , converter::to_python_function_t + , converter::convertible_function + , converter::constructor_function + , type_info + , const char *doc = 0 + ); + + void add_value(char const* name, long value); + void export_values(); + + static PyObject* to_python(PyTypeObject* type, long x); +}; + +}}} // namespace boost::python::object + +#endif // ENUM_BASE_DWA200298_HPP diff --git a/boost/python/object/find_instance.hpp b/boost/python/object/find_instance.hpp new file mode 100644 index 0000000000..3202c1cd15 --- /dev/null +++ b/boost/python/object/find_instance.hpp @@ -0,0 +1,21 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef FIND_INSTANCE_DWA2002312_HPP +# define FIND_INSTANCE_DWA2002312_HPP + +# include <boost/python/type_id.hpp> + +namespace boost { namespace python { namespace objects { + +// Given a type_id, find the instance data which corresponds to it, or +// return 0 in case no such type is held. If null_shared_ptr_only is +// true and the type being sought is a shared_ptr, only find an +// instance if it turns out to be NULL. Needed for shared_ptr rvalue +// from_python support. +BOOST_PYTHON_DECL void* find_instance_impl(PyObject*, type_info, bool null_shared_ptr_only = false); + +}}} // namespace boost::python::objects + +#endif // FIND_INSTANCE_DWA2002312_HPP diff --git a/boost/python/object/forward.hpp b/boost/python/object/forward.hpp new file mode 100644 index 0000000000..2faf3321ec --- /dev/null +++ b/boost/python/object/forward.hpp @@ -0,0 +1,194 @@ +// Copyright David Abrahams 2001. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef FORWARD_DWA20011215_HPP +# define FORWARD_DWA20011215_HPP + +# include <boost/mpl/if.hpp> +# include <boost/type_traits/is_scalar.hpp> +# include <boost/type_traits/add_const.hpp> +# include <boost/type_traits/add_reference.hpp> +# include <boost/ref.hpp> +# include <boost/python/detail/value_arg.hpp> +# include <boost/python/detail/copy_ctor_mutates_rhs.hpp> +# if BOOST_WORKAROUND(BOOST_MSVC, < 1300) +# include <boost/type_traits/is_enum.hpp> +# include <boost/mpl/and.hpp> +# include <boost/mpl/not.hpp> +# else +# include <boost/mpl/or.hpp> +# endif + +namespace boost { namespace python { namespace objects { + +// Very much like boost::reference_wrapper<T>, except that in this +// case T can be a reference already without causing a +// reference-to-reference error. +template <class T> +struct reference_to_value +{ + typedef typename add_reference<typename add_const<T>::type>::type reference; + + reference_to_value(reference x) : m_value(x) {} + reference get() const { return m_value; } + private: + reference m_value; +}; + +// A little metaprogram which selects the type to pass through an +// intermediate forwarding function when the destination argument type +// is T. +template <class T> +struct forward + : mpl::if_< +# if BOOST_WORKAROUND(BOOST_MSVC, < 1300) + // vc6 chokes on unforwarding enums nested in classes + mpl::and_< + is_scalar<T> + , mpl::not_< + is_enum<T> + > + > +# else + mpl::or_<python::detail::copy_ctor_mutates_rhs<T>, is_scalar<T> > +# endif + , T + , reference_to_value<T> + > +{ +}; + +# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +template<typename T> +struct unforward +{ + typedef typename unwrap_reference<T>::type& type; +}; + +template<typename T> +struct unforward<reference_to_value<T> > +{ + typedef T type; +}; + +template <typename T> +struct unforward_cref + : python::detail::value_arg< + typename unwrap_reference<T>::type + > +{ +}; + +template<typename T> +struct unforward_cref<reference_to_value<T> > + : add_reference<typename add_const<T>::type> +{ +}; + +# else // no partial specialization + +namespace detail +{ + typedef char (&yes_reference_to_value_t)[1]; + typedef char (&no_reference_to_value_t)[2]; + + no_reference_to_value_t is_reference_to_value_test(...); + + template<typename T> + yes_reference_to_value_t is_reference_to_value_test(boost::type< reference_to_value<T> >); + + template<bool wrapped> + struct unforwarder + { + template <class T> + struct apply + { + typedef typename unwrap_reference<T>::type& type; + }; + }; + + template<> + struct unforwarder<true> + { + template <class T> + struct apply + { + typedef typename T::reference type; + }; + }; + + template<bool wrapped = false> + struct cref_unforwarder + { + template <class T> + struct apply + : python::detail::value_arg< + typename unwrap_reference<T>::type + > + { + }; + }; + + template<> + struct cref_unforwarder<true> + { + template <class T> + struct apply + : python::detail::value_arg< + typename T::reference + > + { + }; + }; + + template<typename T> + struct is_reference_to_value + { + BOOST_STATIC_CONSTANT( + bool, value = ( + sizeof(is_reference_to_value_test(boost::type<T>())) + == sizeof(yes_reference_to_value_t))); + typedef mpl::bool_<value> type; + }; +} + +template <typename T> +struct unforward + : public detail::unforwarder< + detail::is_reference_to_value<T>::value + >::template apply<T> +{}; + +template <typename T> +struct unforward_cref + : public detail::cref_unforwarder< + detail::is_reference_to_value<T>::value + >::template apply<T> +{}; + +# endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + +template <class T> +typename reference_to_value<T>::reference +do_unforward(reference_to_value<T> const& x, int) +{ + return x.get(); +} + +template <class T> +typename reference_wrapper<T>::type& +do_unforward(reference_wrapper<T> const& x, int) +{ + return x.get(); +} + +template <class T> +T const& do_unforward(T const& x, ...) +{ + return x; +} + +}}} // namespace boost::python::objects + +#endif // FORWARD_DWA20011215_HPP diff --git a/boost/python/object/function.hpp b/boost/python/object/function.hpp new file mode 100644 index 0000000000..f29d344820 --- /dev/null +++ b/boost/python/object/function.hpp @@ -0,0 +1,82 @@ +// Copyright David Abrahams 2001. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef FUNCTION_DWA20011214_HPP +# define FUNCTION_DWA20011214_HPP + +# include <boost/python/detail/prefix.hpp> +# include <boost/python/args_fwd.hpp> +# include <boost/python/handle.hpp> +# include <boost/function/function2.hpp> +# include <boost/python/object_core.hpp> +# include <boost/python/object/py_function.hpp> + +namespace boost { namespace python { namespace objects { + + +struct BOOST_PYTHON_DECL function : PyObject +{ + function( + py_function const& + , python::detail::keyword const* names_and_defaults + , unsigned num_keywords); + + ~function(); + + PyObject* call(PyObject*, PyObject*) const; + + // Add an attribute to the name_space with the given name. If it is + // a function object (this class), and an existing function is + // already there, add it as an overload. + static void add_to_namespace( + object const& name_space, char const* name, object const& attribute); + + static void add_to_namespace( + object const& name_space, char const* name, object const& attribute, char const* doc); + + object const& doc() const; + void doc(object const& x); + + object const& name() const; + + object const& get_namespace() const { return m_namespace; } + + private: // helper functions + object signature(bool show_return_type=false) const; + object signatures(bool show_return_type=false) const; + void argument_error(PyObject* args, PyObject* keywords) const; + void add_overload(handle<function> const&); + + private: // data members + py_function m_fn; + handle<function> m_overloads; + object m_name; + object m_namespace; + object m_doc; + object m_arg_names; + unsigned m_nkeyword_values; + friend class function_doc_signature_generator; +}; + +// +// implementations +// +inline object const& function::doc() const +{ + return this->m_doc; +} + +inline void function::doc(object const& x) +{ + this->m_doc = x; +} + +inline object const& function::name() const +{ + return this->m_name; +} + +}}} // namespace boost::python::objects + +#endif // FUNCTION_DWA20011214_HPP diff --git a/boost/python/object/function_doc_signature.hpp b/boost/python/object/function_doc_signature.hpp new file mode 100644 index 0000000000..4f00cb385a --- /dev/null +++ b/boost/python/object/function_doc_signature.hpp @@ -0,0 +1,36 @@ +// Copyright Nikolay Mladenov 2007. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef FUNCTION_SIGNATURE_20070531_HPP +# define FUNCTION_SIGNATURE_20070531_HPP + +#include <boost/python/object/function.hpp> +#include <boost/python/converter/registrations.hpp> +#include <boost/python/str.hpp> +#include <boost/python/tuple.hpp> + +#include <boost/python/detail/signature.hpp> + + +#include <vector> + +namespace boost { namespace python { namespace objects { + +class function_doc_signature_generator{ + static const char * py_type_str(const python::detail::signature_element &s); + static bool arity_cmp( function const *f1, function const *f2 ); + static bool are_seq_overloads( function const *f1, function const *f2 , bool check_docs); + static std::vector<function const*> flatten(function const *f); + static std::vector<function const*> split_seq_overloads( const std::vector<function const *> &funcs, bool split_on_doc_change); + static str raw_function_pretty_signature(function const *f, size_t n_overloads, bool cpp_types = false); + static str parameter_string(py_function const &f, size_t n, object arg_names, bool cpp_types); + static str pretty_signature(function const *f, size_t n_overloads, bool cpp_types = false); + +public: + static list function_doc_signatures( function const * f); +}; + +}}}//end of namespace boost::python::objects + +#endif //FUNCTION_SIGNATURE_20070531_HPP diff --git a/boost/python/object/function_handle.hpp b/boost/python/object/function_handle.hpp new file mode 100644 index 0000000000..7edaf2ce3a --- /dev/null +++ b/boost/python/object/function_handle.hpp @@ -0,0 +1,44 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef FUNCTION_HANDLE_DWA2002725_HPP +# define FUNCTION_HANDLE_DWA2002725_HPP +# include <boost/python/handle.hpp> +# include <boost/python/detail/caller.hpp> +# include <boost/python/default_call_policies.hpp> +# include <boost/python/object/py_function.hpp> +# include <boost/python/signature.hpp> + +namespace boost { namespace python { namespace objects { + +BOOST_PYTHON_DECL handle<> function_handle_impl(py_function const& f); + +// Just like function_object, but returns a handle<> instead. Using +// this for arg_to_python<> allows us to break a circular dependency +// between object and arg_to_python. +template <class F, class Signature> +inline handle<> function_handle(F const& f, Signature) +{ + enum { n_arguments = mpl::size<Signature>::value - 1 }; + + return objects::function_handle_impl( + python::detail::caller< + F,default_call_policies,Signature + >( + f, default_call_policies() + ) + ); +} + +// Just like make_function, but returns a handle<> intead. Same +// reasoning as above. +template <class F> +handle<> make_function_handle(F f) +{ + return objects::function_handle(f, python::detail::get_signature(f)); +} + +}}} // namespace boost::python::objects + +#endif // FUNCTION_HANDLE_DWA2002725_HPP diff --git a/boost/python/object/function_object.hpp b/boost/python/object/function_object.hpp new file mode 100644 index 0000000000..eaa079fbe0 --- /dev/null +++ b/boost/python/object/function_object.hpp @@ -0,0 +1,40 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef FUNCTION_OBJECT_DWA2002725_HPP +# define FUNCTION_OBJECT_DWA2002725_HPP +# include <boost/python/detail/prefix.hpp> +# include <boost/function/function2.hpp> +# include <boost/python/object_core.hpp> +# include <boost/python/args_fwd.hpp> +# include <boost/python/object/py_function.hpp> + +namespace boost { namespace python { + +namespace objects +{ + BOOST_PYTHON_DECL api::object function_object( + py_function const& f + , python::detail::keyword_range const&); + + BOOST_PYTHON_DECL api::object function_object( + py_function const& f + , python::detail::keyword_range const&); + + BOOST_PYTHON_DECL api::object function_object(py_function const& f); + + // Add an attribute to the name_space with the given name. If it is + // a Boost.Python function object + // (boost/python/object/function.hpp), and an existing function is + // already there, add it as an overload. + BOOST_PYTHON_DECL void add_to_namespace( + object const& name_space, char const* name, object const& attribute); + + BOOST_PYTHON_DECL void add_to_namespace( + object const& name_space, char const* name, object const& attribute, char const* doc); +} + +}} // namespace boost::python::objects + +#endif // FUNCTION_OBJECT_DWA2002725_HPP diff --git a/boost/python/object/inheritance.hpp b/boost/python/object/inheritance.hpp new file mode 100644 index 0000000000..b49a0442e2 --- /dev/null +++ b/boost/python/object/inheritance.hpp @@ -0,0 +1,132 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef INHERITANCE_DWA200216_HPP +# define INHERITANCE_DWA200216_HPP + +# include <boost/python/type_id.hpp> +# include <boost/shared_ptr.hpp> +# include <boost/mpl/if.hpp> +# include <boost/type_traits/is_polymorphic.hpp> +# include <boost/type_traits/is_base_and_derived.hpp> +# include <boost/detail/workaround.hpp> + +namespace boost { namespace python { namespace objects { + +typedef type_info class_id; +using python::type_id; + +// Types used to get address and id of most derived type +typedef std::pair<void*,class_id> dynamic_id_t; +typedef dynamic_id_t (*dynamic_id_function)(void*); + +BOOST_PYTHON_DECL void register_dynamic_id_aux( + class_id static_id, dynamic_id_function get_dynamic_id); + +BOOST_PYTHON_DECL void add_cast( + class_id src_t, class_id dst_t, void* (*cast)(void*), bool is_downcast); + +// +// a generator with an execute() function which, given a source type +// and a pointer to an object of that type, returns its most-derived +// /reachable/ type identifier and object pointer. +// + +// first, the case where T has virtual functions +template <class T> +struct polymorphic_id_generator +{ + static dynamic_id_t execute(void* p_) + { + T* p = static_cast<T*>(p_); + return std::make_pair(dynamic_cast<void*>(p), class_id(typeid(*p))); + } +}; + +// now, the non-polymorphic case. +template <class T> +struct non_polymorphic_id_generator +{ + static dynamic_id_t execute(void* p_) + { + return std::make_pair(p_, python::type_id<T>()); + } +}; + +// Now the generalized selector +template <class T> +struct dynamic_id_generator + : mpl::if_< + boost::is_polymorphic<T> + , boost::python::objects::polymorphic_id_generator<T> + , boost::python::objects::non_polymorphic_id_generator<T> + > +{}; + +// Register the dynamic id function for T with the type-conversion +// system. +template <class T> +void register_dynamic_id(T* = 0) +{ + typedef typename dynamic_id_generator<T>::type generator; + register_dynamic_id_aux( + python::type_id<T>(), &generator::execute); +} + +// +// a generator with an execute() function which, given a void* +// pointing to an object of type Source will attempt to convert it to +// an object of type Target. +// + +template <class Source, class Target> +struct dynamic_cast_generator +{ + static void* execute(void* source) + { + return dynamic_cast<Target*>( + static_cast<Source*>(source)); + } + +}; + +template <class Source, class Target> +struct implicit_cast_generator +{ + static void* execute(void* source) + { + Target* result = static_cast<Source*>(source); + return result; + } +}; + +template <class Source, class Target> +struct cast_generator + : mpl::if_< + is_base_and_derived<Target,Source> + , implicit_cast_generator<Source,Target> + , dynamic_cast_generator<Source,Target> + > +{ +}; + +template <class Source, class Target> +inline void register_conversion( + bool is_downcast = ::boost::is_base_and_derived<Source,Target>::value + // These parameters shouldn't be used; they're an MSVC bug workaround + , Source* = 0, Target* = 0) +{ + typedef typename cast_generator<Source,Target>::type generator; + + add_cast( + python::type_id<Source>() + , python::type_id<Target>() + , &generator::execute + , is_downcast + ); +} + +}}} // namespace boost::python::object + +#endif // INHERITANCE_DWA200216_HPP diff --git a/boost/python/object/inheritance_query.hpp b/boost/python/object/inheritance_query.hpp new file mode 100644 index 0000000000..916e161f29 --- /dev/null +++ b/boost/python/object/inheritance_query.hpp @@ -0,0 +1,17 @@ +// Copyright David Abrahams 2003. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef INHERITANCE_QUERY_DWA2003520_HPP +# define INHERITANCE_QUERY_DWA2003520_HPP + +# include <boost/python/type_id.hpp> + +namespace boost { namespace python { namespace objects { + +BOOST_PYTHON_DECL void* find_static_type(void* p, type_info src, type_info dst); +BOOST_PYTHON_DECL void* find_dynamic_type(void* p, type_info src, type_info dst); + +}}} // namespace boost::python::object + +#endif // INHERITANCE_QUERY_DWA2003520_HPP diff --git a/boost/python/object/instance.hpp b/boost/python/object/instance.hpp new file mode 100644 index 0000000000..177576ef82 --- /dev/null +++ b/boost/python/object/instance.hpp @@ -0,0 +1,51 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef INSTANCE_DWA200295_HPP +# define INSTANCE_DWA200295_HPP + +# include <boost/python/detail/prefix.hpp> +# include <boost/type_traits/alignment_traits.hpp> +# include <cstddef> + +namespace boost { namespace python +{ + struct BOOST_PYTHON_DECL_FORWARD instance_holder; +}} // namespace boost::python + +namespace boost { namespace python { namespace objects { + +// Each extension instance will be one of these +template <class Data = char> +struct instance +{ + PyObject_VAR_HEAD + PyObject* dict; + PyObject* weakrefs; + instance_holder* objects; + + typedef typename type_with_alignment< + ::boost::alignment_of<Data>::value + >::type align_t; + + union + { + align_t align; + char bytes[sizeof(Data)]; + } storage; +}; + +template <class Data> +struct additional_instance_size +{ + typedef instance<Data> instance_data; + typedef instance<char> instance_char; + BOOST_STATIC_CONSTANT( + std::size_t, value = sizeof(instance_data) + - BOOST_PYTHON_OFFSETOF(instance_char,storage)); +}; + +}}} // namespace boost::python::object + +#endif // INSTANCE_DWA200295_HPP diff --git a/boost/python/object/iterator.hpp b/boost/python/object/iterator.hpp new file mode 100644 index 0000000000..ab748fe82d --- /dev/null +++ b/boost/python/object/iterator.hpp @@ -0,0 +1,258 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef ITERATOR_DWA2002510_HPP +# define ITERATOR_DWA2002510_HPP + +# include <boost/python/detail/prefix.hpp> + +# include <boost/python/class.hpp> +# include <boost/python/return_value_policy.hpp> +# include <boost/python/return_by_value.hpp> +# include <boost/python/handle.hpp> +# include <boost/python/make_function.hpp> + +# include <boost/python/object/iterator_core.hpp> +# include <boost/python/object/class_detail.hpp> +# include <boost/python/object/function_object.hpp> + +# include <boost/mpl/vector/vector10.hpp> +# include <boost/mpl/if.hpp> + +# include <boost/python/detail/raw_pyobject.hpp> + +# include <boost/type.hpp> + +# include <boost/type_traits/is_same.hpp> +# include <boost/type_traits/add_reference.hpp> +# include <boost/type_traits/add_const.hpp> + +# include <boost/detail/iterator.hpp> + +namespace boost { namespace python { namespace objects { + +// CallPolicies for the next() method of iterators. We don't want +// users to have to explicitly specify that the references returned by +// iterators are copied, so we just replace the result_converter from +// the default_iterator_call_policies with a permissive one which +// always copies the result. +typedef return_value_policy<return_by_value> default_iterator_call_policies; + +// Instantiations of these are wrapped to produce Python iterators. +template <class NextPolicies, class Iterator> +struct iterator_range +{ + iterator_range(object sequence, Iterator start, Iterator finish); + + typedef boost::detail::iterator_traits<Iterator> traits_t; + + struct next + { + typedef typename mpl::if_< + is_reference< + typename traits_t::reference + > + , typename traits_t::reference + , typename traits_t::value_type + >::type result_type; + + result_type + operator()(iterator_range<NextPolicies,Iterator>& self) + { + if (self.m_start == self.m_finish) + stop_iteration_error(); + return *self.m_start++; + } + +# if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003)) + // CWPro8 has a codegen problem when this is an empty class + int garbage; +# endif + }; + +# ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + // for compilers which can't deduce the value_type of pointers, we + // have a special implementation of next. This takes advantage of + // the fact that T* results are treated like T& results by + // Boost.Python's function wrappers. + struct next_ptr + { + typedef Iterator result_type; + + result_type + operator()(iterator_range<NextPolicies,Iterator>& self) + { + if (self.m_start == self.m_finish) + stop_iteration_error(); + return self.m_start++; + } + }; + + typedef mpl::if_< + is_same< + boost::detail::please_invoke_BOOST_TT_BROKEN_COMPILER_SPEC_on_cv_unqualified_pointee<Iterator> + , typename traits_t::value_type + > + , next_ptr + , next + >::type next_fn; +# else + typedef next next_fn; +# endif + + object m_sequence; // Keeps the sequence alive while iterating. + Iterator m_start; + Iterator m_finish; +}; + +namespace detail +{ + // Get a Python class which contains the given iterator and + // policies, creating it if necessary. Requires: NextPolicies is + // default-constructible. + template <class Iterator, class NextPolicies> + object demand_iterator_class(char const* name, Iterator* = 0, NextPolicies const& policies = NextPolicies()) + { + typedef iterator_range<NextPolicies,Iterator> range_; + + // Check the registry. If one is already registered, return it. + handle<> class_obj( + objects::registered_class_object(python::type_id<range_>())); + + if (class_obj.get() != 0) + return object(class_obj); + + typedef typename range_::next_fn next_fn; + typedef typename next_fn::result_type result_type; + + return class_<range_>(name, no_init) + .def("__iter__", identity_function()) + .def( +#if PY_VERSION_HEX >= 0x03000000 + "__next__" +#else + "next" +#endif + , make_function( + next_fn() + , policies + , mpl::vector2<result_type,range_&>() + )); + } + + // A function object which builds an iterator_range. + template < + class Target + , class Iterator + , class Accessor1 + , class Accessor2 + , class NextPolicies + > + struct py_iter_ + { + py_iter_(Accessor1 const& get_start, Accessor2 const& get_finish) + : m_get_start(get_start) + , m_get_finish(get_finish) + {} + + // Extract an object x of the Target type from the first Python + // argument, and invoke get_start(x)/get_finish(x) to produce + // iterators, which are used to construct a new iterator_range<> + // object that gets wrapped into a Python iterator. + iterator_range<NextPolicies,Iterator> + operator()(back_reference<Target&> x) const + { + // Make sure the Python class is instantiated. + detail::demand_iterator_class("iterator", (Iterator*)0, NextPolicies()); + + return iterator_range<NextPolicies,Iterator>( + x.source() + , m_get_start(x.get()) + , m_get_finish(x.get()) + ); + } + private: + Accessor1 m_get_start; + Accessor2 m_get_finish; + }; + + template <class Target, class Iterator, class NextPolicies, class Accessor1, class Accessor2> + inline object make_iterator_function( + Accessor1 const& get_start + , Accessor2 const& get_finish + , NextPolicies const& /*next_policies*/ + , Iterator const& (*)() + , boost::type<Target>* + , int + ) + { + return make_function( + py_iter_<Target,Iterator,Accessor1,Accessor2,NextPolicies>(get_start, get_finish) + , default_call_policies() + , mpl::vector2<iterator_range<NextPolicies,Iterator>, back_reference<Target&> >() + ); + } + + template <class Target, class Iterator, class NextPolicies, class Accessor1, class Accessor2> + inline object make_iterator_function( + Accessor1 const& get_start + , Accessor2 const& get_finish + , NextPolicies const& next_policies + , Iterator& (*)() + , boost::type<Target>* + , ...) + { + return make_iterator_function( + get_start + , get_finish + , next_policies + , (Iterator const&(*)())0 + , (boost::type<Target>*)0 + , 0 + ); + } + +} + +// Create a Python callable object which accepts a single argument +// convertible to the C++ Target type and returns a Python +// iterator. The Python iterator uses get_start(x) and get_finish(x) +// (where x is an instance of Target) to produce begin and end +// iterators for the range, and an instance of NextPolicies is used as +// CallPolicies for the Python iterator's next() function. +template <class Target, class NextPolicies, class Accessor1, class Accessor2> +inline object make_iterator_function( + Accessor1 const& get_start + , Accessor2 const& get_finish + , NextPolicies const& next_policies + , boost::type<Target>* = 0 +) +{ + typedef typename Accessor1::result_type iterator; + typedef typename add_const<iterator>::type iterator_const; + typedef typename add_reference<iterator_const>::type iterator_cref; + + return detail::make_iterator_function( + get_start + , get_finish + , next_policies + , (iterator_cref(*)())0 + , (boost::type<Target>*)0 + , 0 + ); +} + +// +// implementation +// +template <class NextPolicies, class Iterator> +inline iterator_range<NextPolicies,Iterator>::iterator_range( + object sequence, Iterator start, Iterator finish) + : m_sequence(sequence), m_start(start), m_finish(finish) +{ +} + +}}} // namespace boost::python::objects + +#endif // ITERATOR_DWA2002510_HPP diff --git a/boost/python/object/iterator_core.hpp b/boost/python/object/iterator_core.hpp new file mode 100644 index 0000000000..064accc5a8 --- /dev/null +++ b/boost/python/object/iterator_core.hpp @@ -0,0 +1,17 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef ITERATOR_CORE_DWA2002512_HPP +# define ITERATOR_CORE_DWA2002512_HPP + +# include <boost/python/object_fwd.hpp> + +namespace boost { namespace python { namespace objects { + +BOOST_PYTHON_DECL object const& identity_function(); +BOOST_PYTHON_DECL void stop_iteration_error(); + +}}} // namespace boost::python::object + +#endif // ITERATOR_CORE_DWA2002512_HPP diff --git a/boost/python/object/life_support.hpp b/boost/python/object/life_support.hpp new file mode 100644 index 0000000000..9a1b16b689 --- /dev/null +++ b/boost/python/object/life_support.hpp @@ -0,0 +1,15 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef LIFE_SUPPORT_DWA200222_HPP +# define LIFE_SUPPORT_DWA200222_HPP +# include <boost/python/detail/prefix.hpp> + +namespace boost { namespace python { namespace objects { + +BOOST_PYTHON_DECL PyObject* make_nurse_and_patient(PyObject* nurse, PyObject* patient); + +}}} // namespace boost::python::object + +#endif // LIFE_SUPPORT_DWA200222_HPP diff --git a/boost/python/object/make_holder.hpp b/boost/python/object/make_holder.hpp new file mode 100644 index 0000000000..0d54dd9f66 --- /dev/null +++ b/boost/python/object/make_holder.hpp @@ -0,0 +1,109 @@ +#if !defined(BOOST_PP_IS_ITERATING) + +// Copyright David Abrahams 2001. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +# ifndef MAKE_HOLDER_DWA20011215_HPP +# define MAKE_HOLDER_DWA20011215_HPP + +# include <boost/python/detail/prefix.hpp> + +# include <boost/python/object/instance.hpp> +# include <boost/python/converter/registry.hpp> +#if !defined( BOOST_PYTHON_NO_PY_SIGNATURES) && defined( BOOST_PYTHON_PY_SIGNATURES_PROPER_INIT_SELF_TYPE) +# include <boost/python/detail/python_type.hpp> +#endif + +# include <boost/python/object/forward.hpp> +# include <boost/python/detail/preprocessor.hpp> + +# include <boost/mpl/next.hpp> +# include <boost/mpl/begin_end.hpp> +# include <boost/mpl/deref.hpp> + +# include <boost/preprocessor/iterate.hpp> +# include <boost/preprocessor/iteration/local.hpp> +# include <boost/preprocessor/repeat.hpp> +# include <boost/preprocessor/debug/line.hpp> +# include <boost/preprocessor/repetition/enum_trailing_binary_params.hpp> + +# include <cstddef> + +namespace boost { namespace python { namespace objects { + +template <int nargs> struct make_holder; + +# define BOOST_PYTHON_DO_FORWARD_ARG(z, index, _) , f##index(a##index) + +// specializations... +# define BOOST_PP_ITERATION_PARAMS_1 (3, (0, BOOST_PYTHON_MAX_ARITY, <boost/python/object/make_holder.hpp>)) +# include BOOST_PP_ITERATE() + +# undef BOOST_PYTHON_DO_FORWARD_ARG + +}}} // namespace boost::python::objects + +# endif // MAKE_HOLDER_DWA20011215_HPP + +// For gcc 4.4 compatability, we must include the +// BOOST_PP_ITERATION_DEPTH test inside an #else clause. +#else // BOOST_PP_IS_ITERATING +#if BOOST_PP_ITERATION_DEPTH() == 1 +# if !(BOOST_WORKAROUND(__MWERKS__, > 0x3100) \ + && BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3201))) +# line BOOST_PP_LINE(__LINE__, make_holder.hpp) +# endif + +# define N BOOST_PP_ITERATION() + +template <> +struct make_holder<N> +{ + template <class Holder, class ArgList> + struct apply + { +# if N + // Unrolled iteration through each argument type in ArgList, + // choosing the type that will be forwarded on to the holder's + // templated constructor. + typedef typename mpl::begin<ArgList>::type iter0; + +# define BOOST_PP_LOCAL_MACRO(n) \ + typedef typename mpl::deref<iter##n>::type t##n; \ + typedef typename forward<t##n>::type f##n; \ + typedef typename mpl::next<iter##n>::type \ + BOOST_PP_CAT(iter,BOOST_PP_INC(n)); // Next iterator type + +# define BOOST_PP_LOCAL_LIMITS (0, N-1) +# include BOOST_PP_LOCAL_ITERATE() +# endif + + static void execute( +#if !defined( BOOST_PYTHON_NO_PY_SIGNATURES) && defined( BOOST_PYTHON_PY_SIGNATURES_PROPER_INIT_SELF_TYPE) + boost::python::detail::python_class<BOOST_DEDUCED_TYPENAME Holder::value_type> *p +#else + PyObject *p +#endif + BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_Z(1, N, t, a)) + { + typedef instance<Holder> instance_t; + + void* memory = Holder::allocate(p, offsetof(instance_t, storage), sizeof(Holder)); + try { + (new (memory) Holder( + p BOOST_PP_REPEAT_1ST(N, BOOST_PYTHON_DO_FORWARD_ARG, nil)))->install(p); + } + catch(...) { + Holder::deallocate(p, memory); + throw; + } + } + }; +}; + +# undef N + +#endif // BOOST_PP_ITERATION_DEPTH() +#endif diff --git a/boost/python/object/make_instance.hpp b/boost/python/object/make_instance.hpp new file mode 100644 index 0000000000..5f2630adc7 --- /dev/null +++ b/boost/python/object/make_instance.hpp @@ -0,0 +1,78 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef MAKE_INSTANCE_DWA200296_HPP +# define MAKE_INSTANCE_DWA200296_HPP + +# include <boost/python/detail/prefix.hpp> +# include <boost/python/object/instance.hpp> +# include <boost/python/converter/registered.hpp> +# include <boost/python/detail/decref_guard.hpp> +# include <boost/python/detail/none.hpp> +# include <boost/mpl/assert.hpp> +# include <boost/mpl/or.hpp> +# include <boost/type_traits/is_union.hpp> + +namespace boost { namespace python { namespace objects { + +template <class T, class Holder, class Derived> +struct make_instance_impl +{ + typedef objects::instance<Holder> instance_t; + + template <class Arg> + static inline PyObject* execute(Arg& x) + { + BOOST_MPL_ASSERT((mpl::or_<is_class<T>, is_union<T> >)); + + PyTypeObject* type = Derived::get_class_object(x); + + if (type == 0) + return python::detail::none(); + + PyObject* raw_result = type->tp_alloc( + type, objects::additional_instance_size<Holder>::value); + + if (raw_result != 0) + { + python::detail::decref_guard protect(raw_result); + + instance_t* instance = (instance_t*)raw_result; + + // construct the new C++ object and install the pointer + // in the Python object. + Derived::construct(&instance->storage, (PyObject*)instance, x)->install(raw_result); + + // Note the position of the internally-stored Holder, + // for the sake of destruction + Py_SIZE(instance) = offsetof(instance_t, storage); + + // Release ownership of the python object + protect.cancel(); + } + return raw_result; + } +}; + + +template <class T, class Holder> +struct make_instance + : make_instance_impl<T, Holder, make_instance<T,Holder> > +{ + template <class U> + static inline PyTypeObject* get_class_object(U&) + { + return converter::registered<T>::converters.get_class_object(); + } + + static inline Holder* construct(void* storage, PyObject* instance, reference_wrapper<T const> x) + { + return new (storage) Holder(instance, x); + } +}; + + +}}} // namespace boost::python::object + +#endif // MAKE_INSTANCE_DWA200296_HPP diff --git a/boost/python/object/make_ptr_instance.hpp b/boost/python/object/make_ptr_instance.hpp new file mode 100644 index 0000000000..9fdb23f6be --- /dev/null +++ b/boost/python/object/make_ptr_instance.hpp @@ -0,0 +1,72 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef MAKE_PTR_INSTANCE_DWA200296_HPP +# define MAKE_PTR_INSTANCE_DWA200296_HPP + +# include <boost/python/object/make_instance.hpp> +# include <boost/python/converter/registry.hpp> +# include <boost/type_traits/is_polymorphic.hpp> +# include <boost/get_pointer.hpp> +# include <boost/detail/workaround.hpp> +# include <typeinfo> + +namespace boost { namespace python { namespace objects { + +template <class T, class Holder> +struct make_ptr_instance + : make_instance_impl<T, Holder, make_ptr_instance<T,Holder> > +{ + template <class Arg> + static inline Holder* construct(void* storage, PyObject*, Arg& x) + { + return new (storage) Holder(x); + } + + template <class Ptr> + static inline PyTypeObject* get_class_object(Ptr const& x) + { + return get_class_object_impl(get_pointer(x)); + } +#ifndef BOOST_PYTHON_NO_PY_SIGNATURES + static inline PyTypeObject const* get_pytype() + { + return converter::registered<T>::converters.get_class_object(); + } +#endif + private: + template <class U> + static inline PyTypeObject* get_class_object_impl(U const volatile* p) + { + if (p == 0) + return 0; // means "return None". + + PyTypeObject* derived = get_derived_class_object( + BOOST_DEDUCED_TYPENAME is_polymorphic<U>::type(), p); + + if (derived) + return derived; + return converter::registered<T>::converters.get_class_object(); + } + + template <class U> + static inline PyTypeObject* get_derived_class_object(mpl::true_, U const volatile* x) + { + converter::registration const* r = converter::registry::query( + type_info(typeid(*get_pointer(x))) + ); + return r ? r->m_class_object : 0; + } + + template <class U> + static inline PyTypeObject* get_derived_class_object(mpl::false_, U*) + { + return 0; + } +}; + + +}}} // namespace boost::python::object + +#endif // MAKE_PTR_INSTANCE_DWA200296_HPP diff --git a/boost/python/object/pickle_support.hpp b/boost/python/object/pickle_support.hpp new file mode 100644 index 0000000000..cbdbcbb9d6 --- /dev/null +++ b/boost/python/object/pickle_support.hpp @@ -0,0 +1,124 @@ +// (C) Copyright R.W. Grosse-Kunstleve 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef BOOST_PYTHON_OBJECT_PICKLE_SUPPORT_RWGK20020603_HPP +# define BOOST_PYTHON_OBJECT_PICKLE_SUPPORT_RWGK20020603_HPP + +# include <boost/python/detail/prefix.hpp> + +namespace boost { namespace python { + +namespace api +{ + class object; +} +using api::object; +class tuple; + +BOOST_PYTHON_DECL object const& make_instance_reduce_function(); + +struct pickle_suite; + +namespace error_messages { + + template <class T> + struct missing_pickle_suite_function_or_incorrect_signature {}; + + inline void must_be_derived_from_pickle_suite(pickle_suite const&) {} +} + +namespace detail { struct pickle_suite_registration; } + +struct pickle_suite +{ + private: + struct inaccessible {}; + friend struct detail::pickle_suite_registration; + public: + static inaccessible* getinitargs() { return 0; } + static inaccessible* getstate() { return 0; } + static inaccessible* setstate() { return 0; } + static bool getstate_manages_dict() { return false; } +}; + +namespace detail { + + struct pickle_suite_registration + { + typedef pickle_suite::inaccessible inaccessible; + + template <class Class_, class Tgetinitargs> + static + void + register_( + Class_& cl, + tuple (*getinitargs_fn)(Tgetinitargs), + inaccessible* (* /*getstate_fn*/)(), + inaccessible* (* /*setstate_fn*/)(), + bool) + { + cl.enable_pickling_(false); + cl.def("__getinitargs__", getinitargs_fn); + } + + template <class Class_, + class Rgetstate, class Tgetstate, + class Tsetstate, class Ttuple> + static + void + register_( + Class_& cl, + inaccessible* (* /*getinitargs_fn*/)(), + Rgetstate (*getstate_fn)(Tgetstate), + void (*setstate_fn)(Tsetstate, Ttuple), + bool getstate_manages_dict) + { + cl.enable_pickling_(getstate_manages_dict); + cl.def("__getstate__", getstate_fn); + cl.def("__setstate__", setstate_fn); + } + + template <class Class_, + class Tgetinitargs, + class Rgetstate, class Tgetstate, + class Tsetstate, class Ttuple> + static + void + register_( + Class_& cl, + tuple (*getinitargs_fn)(Tgetinitargs), + Rgetstate (*getstate_fn)(Tgetstate), + void (*setstate_fn)(Tsetstate, Ttuple), + bool getstate_manages_dict) + { + cl.enable_pickling_(getstate_manages_dict); + cl.def("__getinitargs__", getinitargs_fn); + cl.def("__getstate__", getstate_fn); + cl.def("__setstate__", setstate_fn); + } + + template <class Class_> + static + void + register_( + Class_&, + ...) + { + typedef typename + error_messages::missing_pickle_suite_function_or_incorrect_signature< + Class_>::error_type error_type; + } + }; + + template <typename PickleSuiteType> + struct pickle_suite_finalize + : PickleSuiteType, + pickle_suite_registration + {}; + +} // namespace detail + +}} // namespace boost::python + +#endif // BOOST_PYTHON_OBJECT_PICKLE_SUPPORT_RWGK20020603_HPP diff --git a/boost/python/object/pointer_holder.hpp b/boost/python/object/pointer_holder.hpp new file mode 100644 index 0000000000..4627e34ad2 --- /dev/null +++ b/boost/python/object/pointer_holder.hpp @@ -0,0 +1,224 @@ +#if !defined(BOOST_PP_IS_ITERATING) + +// Copyright David Abrahams 2001. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +# ifndef POINTER_HOLDER_DWA20011215_HPP +# define POINTER_HOLDER_DWA20011215_HPP + +# include <boost/get_pointer.hpp> +# include <boost/type.hpp> + +# include <boost/python/instance_holder.hpp> +# include <boost/python/object/inheritance_query.hpp> +# include <boost/python/object/forward.hpp> + +# include <boost/python/pointee.hpp> +# include <boost/python/type_id.hpp> + +# include <boost/python/detail/wrapper_base.hpp> +# include <boost/python/detail/force_instantiate.hpp> +# include <boost/python/detail/preprocessor.hpp> + + +# include <boost/mpl/if.hpp> +# include <boost/mpl/apply.hpp> + +# include <boost/preprocessor/comma_if.hpp> +# include <boost/preprocessor/iterate.hpp> +# include <boost/preprocessor/repeat.hpp> +# include <boost/preprocessor/debug/line.hpp> +# include <boost/preprocessor/enum_params.hpp> +# include <boost/preprocessor/repetition/enum_binary_params.hpp> + +# include <boost/detail/workaround.hpp> + +# include <boost/type_traits/remove_const.hpp> + +namespace boost { namespace python { + +template <class T> class wrapper; + +}} + + +namespace boost { namespace python { namespace objects { + +# if BOOST_WORKAROUND(__GNUC__, == 2) +# define BOOST_PYTHON_UNFORWARD_LOCAL(z, n, _) BOOST_PP_COMMA_IF(n) (typename unforward<A##n>::type)objects::do_unforward(a##n,0) +# else +# define BOOST_PYTHON_UNFORWARD_LOCAL(z, n, _) BOOST_PP_COMMA_IF(n) objects::do_unforward(a##n,0) +# endif + +template <class Pointer, class Value> +struct pointer_holder : instance_holder +{ + typedef Value value_type; + + pointer_holder(Pointer); + + // Forward construction to the held object + +# define BOOST_PP_ITERATION_PARAMS_1 (4, (0, BOOST_PYTHON_MAX_ARITY, <boost/python/object/pointer_holder.hpp>, 1)) +# include BOOST_PP_ITERATE() + + private: // types + + private: // required holder implementation + void* holds(type_info, bool null_ptr_only); + + template <class T> + inline void* holds_wrapped(type_info dst_t, wrapper<T>*,T* p) + { + return python::type_id<T>() == dst_t ? p : 0; + } + + inline void* holds_wrapped(type_info, ...) + { + return 0; + } + + private: // data members + Pointer m_p; +}; + +template <class Pointer, class Value> +struct pointer_holder_back_reference : instance_holder +{ + private: + typedef typename python::pointee<Pointer>::type held_type; + public: + typedef Value value_type; + + // Not sure about this one -- can it work? The source object + // undoubtedly does not carry the correct back reference pointer. + pointer_holder_back_reference(Pointer); + + // Forward construction to the held object +# define BOOST_PP_ITERATION_PARAMS_1 (4, (0, BOOST_PYTHON_MAX_ARITY, <boost/python/object/pointer_holder.hpp>, 2)) +# include BOOST_PP_ITERATE() + + private: // required holder implementation + void* holds(type_info, bool null_ptr_only); + + private: // data members + Pointer m_p; +}; + +# undef BOOST_PYTHON_UNFORWARD_LOCAL + +template <class Pointer, class Value> +inline pointer_holder<Pointer,Value>::pointer_holder(Pointer p) + : m_p(p) +{ +} + +template <class Pointer, class Value> +inline pointer_holder_back_reference<Pointer,Value>::pointer_holder_back_reference(Pointer p) + : m_p(p) +{ +} + +template <class Pointer, class Value> +void* pointer_holder<Pointer, Value>::holds(type_info dst_t, bool null_ptr_only) +{ + typedef typename boost::remove_const< Value >::type non_const_value; + + if (dst_t == python::type_id<Pointer>() + && !(null_ptr_only && get_pointer(this->m_p)) + ) + return &this->m_p; + + Value* p0 +# if BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x590)) + = static_cast<Value*>( get_pointer(this->m_p) ) +# else + = get_pointer(this->m_p) +# endif + ; + non_const_value* p = const_cast<non_const_value*>( p0 ); + + if (p == 0) + return 0; + + if (void* wrapped = holds_wrapped(dst_t, p, p)) + return wrapped; + + type_info src_t = python::type_id<non_const_value>(); + return src_t == dst_t ? p : find_dynamic_type(p, src_t, dst_t); +} + +template <class Pointer, class Value> +void* pointer_holder_back_reference<Pointer, Value>::holds(type_info dst_t, bool null_ptr_only) +{ + if (dst_t == python::type_id<Pointer>() + && !(null_ptr_only && get_pointer(this->m_p)) + ) + return &this->m_p; + + if (!get_pointer(this->m_p)) + return 0; + + Value* p = get_pointer(m_p); + + if (dst_t == python::type_id<held_type>()) + return p; + + type_info src_t = python::type_id<Value>(); + return src_t == dst_t ? p : find_dynamic_type(p, src_t, dst_t); +} + +}}} // namespace boost::python::objects + +# endif // POINTER_HOLDER_DWA20011215_HPP + +/* --------------- pointer_holder --------------- */ +// For gcc 4.4 compatability, we must include the +// BOOST_PP_ITERATION_DEPTH test inside an #else clause. +#else // BOOST_PP_IS_ITERATING +#if BOOST_PP_ITERATION_DEPTH() == 1 && BOOST_PP_ITERATION_FLAGS() == 1 +# if !(BOOST_WORKAROUND(__MWERKS__, > 0x3100) \ + && BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3201))) +# line BOOST_PP_LINE(__LINE__, pointer_holder.hpp) +# endif + +# define N BOOST_PP_ITERATION() + +# if (N != 0) + template< BOOST_PP_ENUM_PARAMS_Z(1, N, class A) > +# endif + pointer_holder(PyObject* self BOOST_PP_COMMA_IF(N) BOOST_PP_ENUM_BINARY_PARAMS_Z(1, N, A, a)) + : m_p(new Value( + BOOST_PP_REPEAT_1ST(N, BOOST_PYTHON_UNFORWARD_LOCAL, nil) + )) + { + python::detail::initialize_wrapper(self, get_pointer(this->m_p)); + } + +# undef N + +/* --------------- pointer_holder_back_reference --------------- */ +#elif BOOST_PP_ITERATION_DEPTH() == 1 && BOOST_PP_ITERATION_FLAGS() == 2 +# if !(BOOST_WORKAROUND(__MWERKS__, > 0x3100) \ + && BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3201))) +# line BOOST_PP_LINE(__LINE__, pointer_holder.hpp(pointer_holder_back_reference)) +# endif + +# define N BOOST_PP_ITERATION() + +# if (N != 0) + template < BOOST_PP_ENUM_PARAMS_Z(1, N, class A) > +# endif + pointer_holder_back_reference( + PyObject* p BOOST_PP_COMMA_IF(N) BOOST_PP_ENUM_BINARY_PARAMS_Z(1, N, A, a)) + : m_p(new held_type( + p BOOST_PP_COMMA_IF(N) BOOST_PP_REPEAT_1ST(N, BOOST_PYTHON_UNFORWARD_LOCAL, nil) + )) + {} + +# undef N + +#endif // BOOST_PP_ITERATION_DEPTH() +#endif diff --git a/boost/python/object/py_function.hpp b/boost/python/object/py_function.hpp new file mode 100644 index 0000000000..ba9aadf49f --- /dev/null +++ b/boost/python/object/py_function.hpp @@ -0,0 +1,172 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef PY_FUNCTION_DWA200286_HPP +# define PY_FUNCTION_DWA200286_HPP + +# include <boost/python/detail/signature.hpp> +# include <boost/detail/workaround.hpp> +# include <boost/mpl/size.hpp> +# include <memory> + +namespace boost { namespace python { namespace objects { + +// This type is used as a "generalized Python callback", wrapping the +// function signature: +// +// PyObject* (PyObject* args, PyObject* keywords) + +struct BOOST_PYTHON_DECL py_function_impl_base +{ + virtual ~py_function_impl_base(); + virtual PyObject* operator()(PyObject*, PyObject*) = 0; + virtual unsigned min_arity() const = 0; + virtual unsigned max_arity() const; + virtual python::detail::py_func_sig_info signature() const = 0; +}; + +template <class Caller> +struct caller_py_function_impl : py_function_impl_base +{ + caller_py_function_impl(Caller const& caller) + : m_caller(caller) + {} + + PyObject* operator()(PyObject* args, PyObject* kw) + { + return m_caller(args, kw); + } + + virtual unsigned min_arity() const + { + return m_caller.min_arity(); + } + + virtual python::detail::py_func_sig_info signature() const + { + return m_caller.signature(); + } + + private: + Caller m_caller; +}; + +template <class Caller, class Sig> +struct signature_py_function_impl : py_function_impl_base +{ + signature_py_function_impl(Caller const& caller) + : m_caller(caller) + {} + + PyObject* operator()(PyObject* args, PyObject* kw) + { + return m_caller(args, kw); + } + + virtual unsigned min_arity() const + { + return mpl::size<Sig>::value - 1; + } + + virtual python::detail::py_func_sig_info signature() const + { + python::detail::signature_element const* sig = python::detail::signature<Sig>::elements(); + python::detail::py_func_sig_info res = {sig, sig}; + return res; + } + + private: + Caller m_caller; +}; + +template <class Caller, class Sig> +struct full_py_function_impl : py_function_impl_base +{ + full_py_function_impl(Caller const& caller, unsigned min_arity, unsigned max_arity) + : m_caller(caller) + , m_min_arity(min_arity) + , m_max_arity(max_arity > min_arity ? max_arity : min_arity) + {} + + PyObject* operator()(PyObject* args, PyObject* kw) + { + return m_caller(args, kw); + } + + virtual unsigned min_arity() const + { + return m_min_arity; + } + + virtual unsigned max_arity() const + { + return m_max_arity; + } + + virtual python::detail::py_func_sig_info signature() const + { + python::detail::signature_element const* sig = python::detail::signature<Sig>::elements(); + python::detail::py_func_sig_info res = {sig, sig}; + return res; + } + + private: + Caller m_caller; + unsigned m_min_arity; + unsigned m_max_arity; +}; + +struct py_function +{ + template <class Caller> + py_function(Caller const& caller) + : m_impl(new caller_py_function_impl<Caller>(caller)) + {} + + template <class Caller, class Sig> + py_function(Caller const& caller, Sig) + : m_impl(new signature_py_function_impl<Caller, Sig>(caller)) + {} + + template <class Caller, class Sig> + py_function(Caller const& caller, Sig, int min_arity, int max_arity = 0) + : m_impl(new full_py_function_impl<Caller, Sig>(caller, min_arity, max_arity)) + {} + + py_function(py_function const& rhs) + : m_impl(rhs.m_impl) + {} + + PyObject* operator()(PyObject* args, PyObject* kw) const + { + return (*m_impl)(args, kw); + } + + unsigned min_arity() const + { + return m_impl->min_arity(); + } + + unsigned max_arity() const + { + return m_impl->max_arity(); + } + + python::detail::signature_element const* signature() const + { + return m_impl->signature().signature; + } + + python::detail::signature_element const& get_return_type() const + { + return *m_impl->signature().ret; + } + + private: + mutable std::auto_ptr<py_function_impl_base> m_impl; +}; + +}}} // namespace boost::python::objects + +#endif // PY_FUNCTION_DWA200286_HPP diff --git a/boost/python/object/stl_iterator_core.hpp b/boost/python/object/stl_iterator_core.hpp new file mode 100644 index 0000000000..68e0c2441b --- /dev/null +++ b/boost/python/object/stl_iterator_core.hpp @@ -0,0 +1,27 @@ +// Copyright Eric Niebler 2005. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef STL_ITERATOR_CORE_EAN20051028_HPP +# define STL_ITERATOR_CORE_EAN20051028_HPP + +# include <boost/python/object_fwd.hpp> +# include <boost/python/handle_fwd.hpp> + +namespace boost { namespace python { namespace objects { + +struct BOOST_PYTHON_DECL stl_input_iterator_impl +{ + stl_input_iterator_impl(); + stl_input_iterator_impl(boost::python::object const &ob); + void increment(); + bool equal(stl_input_iterator_impl const &that) const; + boost::python::handle<> const ¤t() const; +private: + boost::python::object it_; + boost::python::handle<> ob_; +}; + +}}} // namespace boost::python::object + +#endif // STL_ITERATOR_CORE_EAN20051028_HPP diff --git a/boost/python/object/value_holder.hpp b/boost/python/object/value_holder.hpp new file mode 100644 index 0000000000..f4d452cab1 --- /dev/null +++ b/boost/python/object/value_holder.hpp @@ -0,0 +1,170 @@ +#if !defined(BOOST_PP_IS_ITERATING) + +// Copyright David Abrahams 2001. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +# ifndef VALUE_HOLDER_DWA20011215_HPP +# define VALUE_HOLDER_DWA20011215_HPP + +# include <boost/python/object/value_holder_fwd.hpp> + +# include <boost/python/instance_holder.hpp> +# include <boost/python/type_id.hpp> +# include <boost/python/wrapper.hpp> + +# include <boost/python/object/inheritance_query.hpp> +# include <boost/python/object/forward.hpp> + +# include <boost/python/detail/force_instantiate.hpp> +# include <boost/python/detail/preprocessor.hpp> + +# include <boost/preprocessor/comma_if.hpp> +# include <boost/preprocessor/enum_params.hpp> +# include <boost/preprocessor/iterate.hpp> +# include <boost/preprocessor/repeat.hpp> +# include <boost/preprocessor/debug/line.hpp> + +# include <boost/preprocessor/repetition/enum_params.hpp> +# include <boost/preprocessor/repetition/enum_binary_params.hpp> + +# include <boost/utility/addressof.hpp> + +namespace boost { namespace python { namespace objects { + +# if BOOST_WORKAROUND(__GNUC__, == 2) +# define BOOST_PYTHON_UNFORWARD_LOCAL(z, n, _) BOOST_PP_COMMA_IF(n) (typename unforward<A##n>::type)objects::do_unforward(a##n,0) +# else +# define BOOST_PYTHON_UNFORWARD_LOCAL(z, n, _) BOOST_PP_COMMA_IF(n) objects::do_unforward(a##n,0) +# endif + +template <class Value> +struct value_holder : instance_holder +{ + typedef Value held_type; + typedef Value value_type; + + // Forward construction to the held object +# define BOOST_PP_ITERATION_PARAMS_1 (4, (0, BOOST_PYTHON_MAX_ARITY, <boost/python/object/value_holder.hpp>, 1)) +# include BOOST_PP_ITERATE() + + private: // required holder implementation + void* holds(type_info, bool null_ptr_only); + + template <class T> + inline void* holds_wrapped(type_info dst_t, wrapper<T>*,T* p) + { + return python::type_id<T>() == dst_t ? p : 0; + } + + inline void* holds_wrapped(type_info, ...) + { + return 0; + } + private: // data members + Value m_held; +}; + +template <class Value, class Held> +struct value_holder_back_reference : instance_holder +{ + typedef Held held_type; + typedef Value value_type; + + // Forward construction to the held object +# define BOOST_PP_ITERATION_PARAMS_1 (4, (0, BOOST_PYTHON_MAX_ARITY, <boost/python/object/value_holder.hpp>, 2)) +# include BOOST_PP_ITERATE() + +private: // required holder implementation + void* holds(type_info, bool null_ptr_only); + + private: // data members + Held m_held; +}; + +# undef BOOST_PYTHON_UNFORWARD_LOCAL + +template <class Value> +void* value_holder<Value>::holds(type_info dst_t, bool /*null_ptr_only*/) +{ + if (void* wrapped = holds_wrapped(dst_t, boost::addressof(m_held), boost::addressof(m_held))) + return wrapped; + + type_info src_t = python::type_id<Value>(); + return src_t == dst_t ? boost::addressof(m_held) + : find_static_type(boost::addressof(m_held), src_t, dst_t); +} + +template <class Value, class Held> +void* value_holder_back_reference<Value,Held>::holds( + type_info dst_t, bool /*null_ptr_only*/) +{ + type_info src_t = python::type_id<Value>(); + Value* x = &m_held; + + if (dst_t == src_t) + return x; + else if (dst_t == python::type_id<Held>()) + return &m_held; + else + return find_static_type(x, src_t, dst_t); +} + +}}} // namespace boost::python::objects + +# endif // VALUE_HOLDER_DWA20011215_HPP + +// --------------- value_holder --------------- + +// For gcc 4.4 compatability, we must include the +// BOOST_PP_ITERATION_DEPTH test inside an #else clause. +#else // BOOST_PP_IS_ITERATING +#if BOOST_PP_ITERATION_DEPTH() == 1 && BOOST_PP_ITERATION_FLAGS() == 1 +# if !(BOOST_WORKAROUND(__MWERKS__, > 0x3100) \ + && BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3201))) +# line BOOST_PP_LINE(__LINE__, value_holder.hpp(value_holder)) +# endif + +# define N BOOST_PP_ITERATION() + +# if (N != 0) + template <BOOST_PP_ENUM_PARAMS_Z(1, N, class A)> +# endif + value_holder( + PyObject* self BOOST_PP_COMMA_IF(N) BOOST_PP_ENUM_BINARY_PARAMS_Z(1, N, A, a)) + : m_held( + BOOST_PP_REPEAT_1ST(N, BOOST_PYTHON_UNFORWARD_LOCAL, nil) + ) + { + python::detail::initialize_wrapper(self, boost::addressof(this->m_held)); + } + +# undef N + +// --------------- value_holder_back_reference --------------- + +#elif BOOST_PP_ITERATION_DEPTH() == 1 && BOOST_PP_ITERATION_FLAGS() == 2 +# if !(BOOST_WORKAROUND(__MWERKS__, > 0x3100) \ + && BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3201))) +# line BOOST_PP_LINE(__LINE__, value_holder.hpp(value_holder_back_reference)) +# endif + +# define N BOOST_PP_ITERATION() + +# if (N != 0) + template <BOOST_PP_ENUM_PARAMS_Z(1, N, class A)> +# endif + value_holder_back_reference( + PyObject* p BOOST_PP_COMMA_IF(N) BOOST_PP_ENUM_BINARY_PARAMS_Z(1, N, A, a)) + : m_held( + p BOOST_PP_COMMA_IF(N) + BOOST_PP_REPEAT_1ST(N, BOOST_PYTHON_UNFORWARD_LOCAL, nil) + ) + { + } + +# undef N + +#endif // BOOST_PP_ITERATION_DEPTH() +#endif diff --git a/boost/python/object/value_holder_fwd.hpp b/boost/python/object/value_holder_fwd.hpp new file mode 100644 index 0000000000..3454bac426 --- /dev/null +++ b/boost/python/object/value_holder_fwd.hpp @@ -0,0 +1,16 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef VALUE_HOLDER_FWD_DWA2002311_HPP +# define VALUE_HOLDER_FWD_DWA2002311_HPP + +namespace boost { namespace python { namespace objects { + +struct no_back_reference; + +template <class CallbackType = no_back_reference> struct value_holder_generator; + +}}} // namespace boost::python::object + +#endif // VALUE_HOLDER_FWD_DWA2002311_HPP diff --git a/boost/python/object_attributes.hpp b/boost/python/object_attributes.hpp new file mode 100644 index 0000000000..26d599113f --- /dev/null +++ b/boost/python/object_attributes.hpp @@ -0,0 +1,116 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef OBJECT_ATTRIBUTES_DWA2002615_HPP +# define OBJECT_ATTRIBUTES_DWA2002615_HPP + +# include <boost/python/detail/prefix.hpp> + +# include <boost/python/proxy.hpp> +# include <boost/python/object_core.hpp> +# include <boost/python/object_protocol.hpp> + +namespace boost { namespace python { namespace api { + +struct const_attribute_policies +{ + typedef char const* key_type; + static object get(object const& target, char const* key); + static object get(object const& target, object const& key); +}; + +struct attribute_policies : const_attribute_policies +{ + static object const& set(object const& target, char const* key, object const& value); + static void del(object const&target, char const* key); +}; + +struct const_objattribute_policies +{ + typedef object const key_type; + static object get(object const& target, object const& key); +}; + +struct objattribute_policies : const_objattribute_policies +{ + static object const& set(object const& target, object const& key, object const& value); + static void del(object const&target, object const& key); +}; + +// +// implementation +// +template <class U> +inline object_attribute object_operators<U>::attr(char const* name) +{ + object_cref2 x = *static_cast<U*>(this); + return object_attribute(x, name); +} + +template <class U> +inline const_object_attribute object_operators<U>::attr(char const* name) const +{ + object_cref2 x = *static_cast<U const*>(this); + return const_object_attribute(x, name); +} + +template <class U> +inline object_objattribute object_operators<U>::attr(object const& name) +{ + object_cref2 x = *static_cast<U*>(this); + return object_objattribute(x, name); +} + +template <class U> +inline const_object_objattribute object_operators<U>::attr(object const& name) const +{ + object_cref2 x = *static_cast<U const*>(this); + return const_object_objattribute(x, name); +} + +inline object const_attribute_policies::get(object const& target, char const* key) +{ + return python::getattr(target, key); +} + +inline object const_objattribute_policies::get(object const& target, object const& key) +{ + return python::getattr(target, key); +} + +inline object const& attribute_policies::set( + object const& target + , char const* key + , object const& value) +{ + python::setattr(target, key, value); + return value; +} + +inline object const& objattribute_policies::set( + object const& target + , object const& key + , object const& value) +{ + python::setattr(target, key, value); + return value; +} + +inline void attribute_policies::del( + object const& target + , char const* key) +{ + python::delattr(target, key); +} + +inline void objattribute_policies::del( + object const& target + , object const& key) +{ + python::delattr(target, key); +} + +}}} // namespace boost::python::api + +#endif // OBJECT_ATTRIBUTES_DWA2002615_HPP diff --git a/boost/python/object_call.hpp b/boost/python/object_call.hpp new file mode 100644 index 0000000000..5c4d0f2fbe --- /dev/null +++ b/boost/python/object_call.hpp @@ -0,0 +1,23 @@ +# if !defined(BOOST_PYTHON_SYNOPSIS) +# // Copyright David Abrahams 2002. +# // Distributed under the Boost Software License, Version 1.0. (See +# // accompanying file LICENSE_1_0.txt or copy at +# // http://www.boost.org/LICENSE_1_0.txt) + +# if !defined(BOOST_PP_IS_ITERATING) +# error Boost.Python - do not include this file! +# endif + +# define N BOOST_PP_ITERATION() + + template <BOOST_PP_ENUM_PARAMS_Z(1, N, class A)> + typename detail::dependent<object, A0>::type + operator()(BOOST_PP_ENUM_BINARY_PARAMS_Z(1, N, A, const& a)) const + { + typedef typename detail::dependent<object, A0>::type obj; + U const& self = *static_cast<U const*>(this); + return call<obj>(get_managed_object(self, tag), BOOST_PP_ENUM_PARAMS_Z(1, N, a)); + } + +# undef N +# endif // BOOST_PYTHON_SYNOPSIS diff --git a/boost/python/object_core.hpp b/boost/python/object_core.hpp new file mode 100644 index 0000000000..4d81e2eae8 --- /dev/null +++ b/boost/python/object_core.hpp @@ -0,0 +1,583 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef OBJECT_CORE_DWA2002615_HPP +# define OBJECT_CORE_DWA2002615_HPP + +# define BOOST_PYTHON_OBJECT_HAS_IS_NONE // added 2010-03-15 by rwgk + +# include <boost/python/detail/prefix.hpp> + +# include <boost/type.hpp> + +# include <boost/python/call.hpp> +# include <boost/python/handle_fwd.hpp> +# include <boost/python/errors.hpp> +# include <boost/python/refcount.hpp> +# include <boost/python/detail/preprocessor.hpp> +# include <boost/python/tag.hpp> +# include <boost/python/def_visitor.hpp> + +# include <boost/python/detail/raw_pyobject.hpp> +# include <boost/python/detail/dependent.hpp> + +# include <boost/python/object/forward.hpp> +# include <boost/python/object/add_to_namespace.hpp> + +# include <boost/preprocessor/iterate.hpp> +# include <boost/preprocessor/debug/line.hpp> + +# include <boost/python/detail/is_xxx.hpp> +# include <boost/python/detail/string_literal.hpp> +# include <boost/python/detail/def_helper_fwd.hpp> + +# include <boost/type_traits/is_same.hpp> +# include <boost/type_traits/is_convertible.hpp> +# include <boost/type_traits/remove_reference.hpp> + +# if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) +# include <boost/type_traits/add_pointer.hpp> +# endif + +# include <boost/mpl/if.hpp> + +namespace boost { namespace python { + +namespace detail +{ + class kwds_proxy; + class args_proxy; +} + +namespace converter +{ + template <class T> struct arg_to_python; +} + +// Put this in an inner namespace so that the generalized operators won't take over +namespace api +{ + +// This file contains the definition of the object class and enough to +// construct/copy it, but not enough to do operations like +// attribute/item access or addition. + + template <class Policies> class proxy; + + struct const_attribute_policies; + struct attribute_policies; + struct const_objattribute_policies; + struct objattribute_policies; + struct const_item_policies; + struct item_policies; + struct const_slice_policies; + struct slice_policies; + class slice_nil; + + typedef proxy<const_attribute_policies> const_object_attribute; + typedef proxy<attribute_policies> object_attribute; + typedef proxy<const_objattribute_policies> const_object_objattribute; + typedef proxy<objattribute_policies> object_objattribute; + typedef proxy<const_item_policies> const_object_item; + typedef proxy<item_policies> object_item; + typedef proxy<const_slice_policies> const_object_slice; + typedef proxy<slice_policies> object_slice; + + // + // is_proxy -- proxy type detection + // + BOOST_PYTHON_IS_XXX_DEF(proxy, boost::python::api::proxy, 1) + + template <class T> struct object_initializer; + + class object; + typedef PyObject* (object::*bool_type)() const; + + template <class U> + class object_operators : public def_visitor<U> + { + protected: +# if !defined(BOOST_MSVC) || BOOST_MSVC >= 1300 + typedef object const& object_cref; +# else + typedef object object_cref; +# endif + public: + // function call + // + object operator()() const; + +# define BOOST_PP_ITERATION_PARAMS_1 (3, (1, BOOST_PYTHON_MAX_ARITY, <boost/python/object_call.hpp>)) +# include BOOST_PP_ITERATE() + + detail::args_proxy operator* () const; + object operator()(detail::args_proxy const &args) const; + object operator()(detail::args_proxy const &args, + detail::kwds_proxy const &kwds) const; + + // truth value testing + // + operator bool_type() const; + bool operator!() const; // needed for vc6 + + // Attribute access + // + const_object_attribute attr(char const*) const; + object_attribute attr(char const*); + const_object_objattribute attr(object const&) const; + object_objattribute attr(object const&); + + // Wrap 'in' operator (aka. __contains__) + template <class T> + object contains(T const& key) const; + + // item access + // + const_object_item operator[](object_cref) const; + object_item operator[](object_cref); + + template <class T> + const_object_item + operator[](T const& key) const +# if !defined(BOOST_MSVC) || BOOST_MSVC > 1300 + ; +# else + { + return (*this)[object(key)]; + } +# endif + + template <class T> + object_item + operator[](T const& key) +# if !defined(BOOST_MSVC) || BOOST_MSVC > 1300 + ; +# else + { + return (*this)[object(key)]; + } +# endif + + // slicing + // + const_object_slice slice(object_cref, object_cref) const; + object_slice slice(object_cref, object_cref); + + const_object_slice slice(slice_nil, object_cref) const; + object_slice slice(slice_nil, object_cref); + + const_object_slice slice(object_cref, slice_nil) const; + object_slice slice(object_cref, slice_nil); + + const_object_slice slice(slice_nil, slice_nil) const; + object_slice slice(slice_nil, slice_nil); + + template <class T, class V> + const_object_slice + slice(T const& start, V const& end) const +# if !defined(BOOST_MSVC) || BOOST_MSVC > 1300 + ; +# else + { + return this->slice( + slice_bound<T>::type(start) + , slice_bound<V>::type(end)); + } +# endif + + template <class T, class V> + object_slice + slice(T const& start, V const& end) +# if !defined(BOOST_MSVC) || BOOST_MSVC > 1300 + ; +# else + { + return this->slice( + slice_bound<T>::type(start) + , slice_bound<V>::type(end)); + } +# endif + + private: // def visitation for adding callable objects as class methods + + template <class ClassT, class DocStringT> + void visit(ClassT& cl, char const* name, python::detail::def_helper<DocStringT> const& helper) const + { + // It's too late to specify anything other than docstrings if + // the callable object is already wrapped. + BOOST_STATIC_ASSERT( + (is_same<char const*,DocStringT>::value + || detail::is_string_literal<DocStringT const>::value)); + + objects::add_to_namespace(cl, name, this->derived_visitor(), helper.doc()); + } + + friend class python::def_visitor_access; + + private: + // there is a confirmed CWPro8 codegen bug here. We prevent the + // early destruction of a temporary by binding a named object + // instead. +# if __MWERKS__ < 0x3000 || __MWERKS__ > 0x3003 + typedef object const& object_cref2; +# else + typedef object const object_cref2; +# endif + }; + + + // VC6 and VC7 require this base class in order to generate the + // correct copy constructor for object. We can't define it there + // explicitly or it will complain of ambiguity. + struct object_base : object_operators<object> + { + // copy constructor without NULL checking, for efficiency. + inline object_base(object_base const&); + inline object_base(PyObject* ptr); + + inline object_base& operator=(object_base const& rhs); + inline ~object_base(); + + // Underlying object access -- returns a borrowed reference + inline PyObject* ptr() const; + + inline bool is_none() const; + + private: + PyObject* m_ptr; + }; + +# ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + template <class T, class U> + struct is_derived_impl + { + static T x; + template <class X> + static X* to_pointer(X const&); + + static char test(U const*); + typedef char (&no)[2]; + static no test(...); + + BOOST_STATIC_CONSTANT(bool, value = sizeof(test(to_pointer(x))) == 1); + }; + + template <class T, class U> + struct is_derived + : mpl::bool_<is_derived_impl<T,U>::value> + {}; +# else + template <class T, class U> + struct is_derived + : is_convertible< + typename remove_reference<T>::type* + , U const* + > + {}; +# endif + + template <class T> + typename objects::unforward_cref<T>::type do_unforward_cref(T const& x) + { +# if BOOST_WORKAROUND(__GNUC__, == 2) + typedef typename objects::unforward_cref<T>::type ret; + return ret(x); +# else + return x; +# endif + } + +# if BOOST_WORKAROUND(__GNUC__, == 2) + // GCC 2.x has non-const string literals; this hacks around that problem. + template <unsigned N> + char const (& do_unforward_cref(char const(&x)[N]) )[N] + { + return x; + } +# endif + + class object; + + template <class T> + PyObject* object_base_initializer(T const& x) + { + typedef typename is_derived< + BOOST_DEDUCED_TYPENAME objects::unforward_cref<T>::type + , object + >::type is_obj; + + return object_initializer< + BOOST_DEDUCED_TYPENAME unwrap_reference<T>::type + >::get( + x + , is_obj() + ); + } + + class object : public object_base + { + public: + // default constructor creates a None object + object(); + + // explicit conversion from any C++ object to Python + template <class T> + explicit object( + T const& x +# if BOOST_WORKAROUND(BOOST_MSVC, < 1300) + // use some SFINAE to un-confuse MSVC about its + // copy-initialization ambiguity claim. + , typename mpl::if_<is_proxy<T>,int&,int>::type* = 0 +# endif + ) + : object_base(object_base_initializer(x)) + { + } + + // Throw error_already_set() if the handle is null. + BOOST_PYTHON_DECL explicit object(handle<> const&); + private: + + public: // implementation detail -- for internal use only + explicit object(detail::borrowed_reference); + explicit object(detail::new_reference); + explicit object(detail::new_non_null_reference); + }; + + // Macros for forwarding constructors in classes derived from + // object. Derived classes will usually want these as an + // implementation detail +# define BOOST_PYTHON_FORWARD_OBJECT_CONSTRUCTORS_(derived, base) \ + inline explicit derived(python::detail::borrowed_reference p) \ + : base(p) {} \ + inline explicit derived(python::detail::new_reference p) \ + : base(p) {} \ + inline explicit derived(python::detail::new_non_null_reference p) \ + : base(p) {} + +# if !defined(BOOST_MSVC) || BOOST_MSVC >= 1300 +# define BOOST_PYTHON_FORWARD_OBJECT_CONSTRUCTORS BOOST_PYTHON_FORWARD_OBJECT_CONSTRUCTORS_ +# else + // MSVC6 has a bug which causes an explicit template constructor to + // be preferred over an appropriate implicit conversion operator + // declared on the argument type. Normally, that would cause a + // runtime failure when using extract<T> to extract a type with a + // templated constructor. This additional constructor will turn that + // runtime failure into an ambiguity error at compile-time due to + // the lack of partial ordering, or at least a link-time error if no + // generalized template constructor is declared. +# define BOOST_PYTHON_FORWARD_OBJECT_CONSTRUCTORS(derived, base) \ + BOOST_PYTHON_FORWARD_OBJECT_CONSTRUCTORS_(derived, base) \ + template <class T> \ + explicit derived(extract<T> const&); +# endif + + // + // object_initializer -- get the handle to construct the object with, + // based on whether T is a proxy or derived from object + // + template <bool is_proxy = false, bool is_object_manager = false> + struct object_initializer_impl + { + static PyObject* + get(object const& x, mpl::true_) + { + return python::incref(x.ptr()); + } + + template <class T> + static PyObject* + get(T const& x, mpl::false_) + { + return python::incref(converter::arg_to_python<T>(x).get()); + } + }; + + template <> + struct object_initializer_impl<true, false> + { + template <class Policies> + static PyObject* + get(proxy<Policies> const& x, mpl::false_) + { + return python::incref(x.operator object().ptr()); + } + }; + + template <> + struct object_initializer_impl<false, true> + { + template <class T, class U> + static PyObject* + get(T const& x, U) + { + return python::incref(get_managed_object(x, boost::python::tag)); + } + }; + + template <> + struct object_initializer_impl<true, true> + {}; // empty implementation should cause an error + + template <class T> + struct object_initializer : object_initializer_impl< + is_proxy<T>::value + , converter::is_object_manager<T>::value + > + {}; + +} +using api::object; +template <class T> struct extract; + +// +// implementation +// + +namespace detail +{ + +class call_proxy +{ +public: + call_proxy(object target) : m_target(target) {} + operator object() const { return m_target;} + + private: + object m_target; +}; + +class kwds_proxy : public call_proxy +{ +public: + kwds_proxy(object o = object()) : call_proxy(o) {} +}; +class args_proxy : public call_proxy +{ +public: + args_proxy(object o) : call_proxy(o) {} + kwds_proxy operator* () const { return kwds_proxy(*this);} +}; +} + +template <typename U> +detail::args_proxy api::object_operators<U>::operator* () const +{ + object_cref2 x = *static_cast<U const*>(this); + return boost::python::detail::args_proxy(x); +} + +template <typename U> +object api::object_operators<U>::operator()(detail::args_proxy const &args) const +{ + U const& self = *static_cast<U const*>(this); + PyObject *result = PyObject_Call(get_managed_object(self, boost::python::tag), + args.operator object().ptr(), + 0); + return object(boost::python::detail::new_reference(result)); + +} + +template <typename U> +object api::object_operators<U>::operator()(detail::args_proxy const &args, + detail::kwds_proxy const &kwds) const +{ + U const& self = *static_cast<U const*>(this); + PyObject *result = PyObject_Call(get_managed_object(self, boost::python::tag), + args.operator object().ptr(), + kwds.operator object().ptr()); + return object(boost::python::detail::new_reference(result)); + +} + + +template <typename U> +template <class T> +object api::object_operators<U>::contains(T const& key) const +{ + return this->attr("__contains__")(object(key)); +} + + +inline object::object() + : object_base(python::incref(Py_None)) +{} + +// copy constructor without NULL checking, for efficiency +inline api::object_base::object_base(object_base const& rhs) + : m_ptr(python::incref(rhs.m_ptr)) +{} + +inline api::object_base::object_base(PyObject* p) + : m_ptr(p) +{} + +inline api::object_base& api::object_base::operator=(api::object_base const& rhs) +{ + Py_INCREF(rhs.m_ptr); + Py_DECREF(this->m_ptr); + this->m_ptr = rhs.m_ptr; + return *this; +} + +inline api::object_base::~object_base() +{ + Py_DECREF(m_ptr); +} + +inline object::object(detail::borrowed_reference p) + : object_base(python::incref((PyObject*)p)) +{} + +inline object::object(detail::new_reference p) + : object_base(expect_non_null((PyObject*)p)) +{} + +inline object::object(detail::new_non_null_reference p) + : object_base((PyObject*)p) +{} + +inline PyObject* api::object_base::ptr() const +{ + return m_ptr; +} + +inline bool api::object_base::is_none() const +{ + return (m_ptr == Py_None); +} + +// +// Converter specialization implementations +// +namespace converter +{ + template <class T> struct object_manager_traits; + + template <> + struct object_manager_traits<object> + { + BOOST_STATIC_CONSTANT(bool, is_specialized = true); + static bool check(PyObject*) { return true; } + + static python::detail::new_non_null_reference adopt(PyObject* x) + { + return python::detail::new_non_null_reference(x); + } +#ifndef BOOST_PYTHON_NO_PY_SIGNATURES + static PyTypeObject const *get_pytype() {return 0;} +#endif + }; +} + +inline PyObject* get_managed_object(object const& x, tag_t) +{ + return x.ptr(); +} + +}} // namespace boost::python + +# include <boost/python/slice_nil.hpp> + +#endif // OBJECT_CORE_DWA2002615_HPP diff --git a/boost/python/object_fwd.hpp b/boost/python/object_fwd.hpp new file mode 100644 index 0000000000..11efcc7075 --- /dev/null +++ b/boost/python/object_fwd.hpp @@ -0,0 +1,18 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef OBJECT_FWD_DWA2002724_HPP +# define OBJECT_FWD_DWA2002724_HPP + +# include <boost/python/detail/prefix.hpp> + +namespace boost { namespace python { +namespace api +{ + class object; +} +using api::object; +}} // namespace boost::python + +#endif // OBJECT_FWD_DWA2002724_HPP diff --git a/boost/python/object_items.hpp b/boost/python/object_items.hpp new file mode 100644 index 0000000000..f0761dadbb --- /dev/null +++ b/boost/python/object_items.hpp @@ -0,0 +1,89 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef OBJECT_ITEMS_DWA2002615_HPP +# define OBJECT_ITEMS_DWA2002615_HPP + +# include <boost/python/detail/prefix.hpp> + +# include <boost/python/proxy.hpp> +# include <boost/python/object_core.hpp> +# include <boost/python/object_protocol.hpp> + +namespace boost { namespace python { namespace api { + +struct const_item_policies +{ + typedef object key_type; + static object get(object const& target, object const& key); +}; + +struct item_policies : const_item_policies +{ + static object const& set(object const& target, object const& key, object const& value); + static void del(object const& target, object const& key); +}; + +// +// implementation +// +template <class U> +inline object_item +object_operators<U>::operator[](object_cref key) +{ + object_cref2 x = *static_cast<U*>(this); + return object_item(x, key); +} + +template <class U> +inline const_object_item +object_operators<U>::operator[](object_cref key) const +{ + object_cref2 x = *static_cast<U const*>(this); + return const_object_item(x, key); +} + +# if !defined(BOOST_MSVC) || BOOST_MSVC > 1300 +template <class U> +template <class T> +inline const_object_item +object_operators<U>::operator[](T const& key) const +{ + return (*this)[object(key)]; +} + +template <class U> +template <class T> +inline object_item +object_operators<U>::operator[](T const& key) +{ + return (*this)[object(key)]; +} +# endif + + +inline object const_item_policies::get(object const& target, object const& key) +{ + return getitem(target, key); +} + +inline object const& item_policies::set( + object const& target + , object const& key + , object const& value) +{ + setitem(target, key, value); + return value; +} + +inline void item_policies::del( + object const& target + , object const& key) +{ + delitem(target, key); +} + +}}} // namespace boost::python::api + +#endif // OBJECT_ITEMS_DWA2002615_HPP diff --git a/boost/python/object_operators.hpp b/boost/python/object_operators.hpp new file mode 100644 index 0000000000..d436bb0144 --- /dev/null +++ b/boost/python/object_operators.hpp @@ -0,0 +1,136 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef OBJECT_OPERATORS_DWA2002617_HPP +# define OBJECT_OPERATORS_DWA2002617_HPP + +# include <boost/python/detail/prefix.hpp> + +# include <boost/python/object_core.hpp> +# include <boost/python/call.hpp> +# include <boost/iterator/detail/enable_if.hpp> +# include <boost/mpl/bool.hpp> + +# include <boost/iterator/detail/config_def.hpp> + +namespace boost { namespace python { namespace api { + +template <class X> +char is_object_operators_helper(object_operators<X> const*); + +typedef char (&no_type)[2]; +no_type is_object_operators_helper(...); + +template <class X> X* make_ptr(); + +template <class L, class R = L> +struct is_object_operators +{ + enum { + value + = (sizeof(api::is_object_operators_helper(api::make_ptr<L>())) + + sizeof(api::is_object_operators_helper(api::make_ptr<R>())) + < 4 + ) + }; + typedef mpl::bool_<value> type; +}; + +# if !defined(BOOST_NO_SFINAE) && !defined(BOOST_NO_IS_CONVERTIBLE) +template <class L, class R, class T> +struct enable_binary + : boost::iterators::enable_if<is_object_operators<L,R>, T> +{}; +# define BOOST_PYTHON_BINARY_RETURN(T) typename enable_binary<L,R,T>::type +# else +# define BOOST_PYTHON_BINARY_RETURN(T) T +# endif + +template <class U> +object object_operators<U>::operator()() const +{ + object_cref2 f = *static_cast<U const*>(this); + return call<object>(f.ptr()); +} + + +template <class U> +inline +object_operators<U>::operator bool_type() const +{ + object_cref2 x = *static_cast<U const*>(this); + int is_true = PyObject_IsTrue(x.ptr()); + if (is_true < 0) throw_error_already_set(); + return is_true ? &object::ptr : 0; +} + +template <class U> +inline bool +object_operators<U>::operator!() const +{ + object_cref2 x = *static_cast<U const*>(this); + int is_true = PyObject_IsTrue(x.ptr()); + if (is_true < 0) throw_error_already_set(); + return !is_true; +} + +# define BOOST_PYTHON_COMPARE_OP(op, opid) \ +template <class L, class R> \ +BOOST_PYTHON_BINARY_RETURN(object) operator op(L const& l, R const& r) \ +{ \ + return PyObject_RichCompare( \ + object(l).ptr(), object(r).ptr(), opid); \ +} +# undef BOOST_PYTHON_COMPARE_OP + +# define BOOST_PYTHON_BINARY_OPERATOR(op) \ +BOOST_PYTHON_DECL object operator op(object const& l, object const& r); \ +template <class L, class R> \ +BOOST_PYTHON_BINARY_RETURN(object) operator op(L const& l, R const& r) \ +{ \ + return object(l) op object(r); \ +} +BOOST_PYTHON_BINARY_OPERATOR(>) +BOOST_PYTHON_BINARY_OPERATOR(>=) +BOOST_PYTHON_BINARY_OPERATOR(<) +BOOST_PYTHON_BINARY_OPERATOR(<=) +BOOST_PYTHON_BINARY_OPERATOR(==) +BOOST_PYTHON_BINARY_OPERATOR(!=) +BOOST_PYTHON_BINARY_OPERATOR(+) +BOOST_PYTHON_BINARY_OPERATOR(-) +BOOST_PYTHON_BINARY_OPERATOR(*) +BOOST_PYTHON_BINARY_OPERATOR(/) +BOOST_PYTHON_BINARY_OPERATOR(%) +BOOST_PYTHON_BINARY_OPERATOR(<<) +BOOST_PYTHON_BINARY_OPERATOR(>>) +BOOST_PYTHON_BINARY_OPERATOR(&) +BOOST_PYTHON_BINARY_OPERATOR(^) +BOOST_PYTHON_BINARY_OPERATOR(|) +# undef BOOST_PYTHON_BINARY_OPERATOR + + +# define BOOST_PYTHON_INPLACE_OPERATOR(op) \ +BOOST_PYTHON_DECL object& operator op(object& l, object const& r); \ +template <class R> \ +object& operator op(object& l, R const& r) \ +{ \ + return l op object(r); \ +} +BOOST_PYTHON_INPLACE_OPERATOR(+=) +BOOST_PYTHON_INPLACE_OPERATOR(-=) +BOOST_PYTHON_INPLACE_OPERATOR(*=) +BOOST_PYTHON_INPLACE_OPERATOR(/=) +BOOST_PYTHON_INPLACE_OPERATOR(%=) +BOOST_PYTHON_INPLACE_OPERATOR(<<=) +BOOST_PYTHON_INPLACE_OPERATOR(>>=) +BOOST_PYTHON_INPLACE_OPERATOR(&=) +BOOST_PYTHON_INPLACE_OPERATOR(^=) +BOOST_PYTHON_INPLACE_OPERATOR(|=) +# undef BOOST_PYTHON_INPLACE_OPERATOR + +}}} // namespace boost::python + +#include <boost/iterator/detail/config_undef.hpp> + +#endif // OBJECT_OPERATORS_DWA2002617_HPP diff --git a/boost/python/object_protocol.hpp b/boost/python/object_protocol.hpp new file mode 100644 index 0000000000..7c1c02830e --- /dev/null +++ b/boost/python/object_protocol.hpp @@ -0,0 +1,90 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef OBJECT_PROTOCOL_DWA2002615_HPP +# define OBJECT_PROTOCOL_DWA2002615_HPP + +# include <boost/python/detail/prefix.hpp> + +# include <boost/python/object_protocol_core.hpp> +# include <boost/python/object_core.hpp> + +# include <boost/detail/workaround.hpp> + +namespace boost { namespace python { namespace api { + +# if BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x590)) +// attempt to use SFINAE to prevent functions accepting T const& from +// coming up as ambiguous with the one taking a char const* when a +// string literal is passed +# define BOOST_PYTHON_NO_ARRAY_ARG(T) , T (*)() = 0 +# else +# define BOOST_PYTHON_NO_ARRAY_ARG(T) +# endif + +template <class Target, class Key> +object getattr(Target const& target, Key const& key BOOST_PYTHON_NO_ARRAY_ARG(Key)) +{ + return getattr(object(target), object(key)); +} + +template <class Target, class Key, class Default> +object getattr(Target const& target, Key const& key, Default const& default_ BOOST_PYTHON_NO_ARRAY_ARG(Key)) +{ + return getattr(object(target), object(key), object(default_)); +} + + +template <class Key, class Value> +void setattr(object const& target, Key const& key, Value const& value BOOST_PYTHON_NO_ARRAY_ARG(Key)) +{ + setattr(target, object(key), object(value)); +} + +template <class Key> +void delattr(object const& target, Key const& key BOOST_PYTHON_NO_ARRAY_ARG(Key)) +{ + delattr(target, object(key)); +} + +template <class Target, class Key> +object getitem(Target const& target, Key const& key BOOST_PYTHON_NO_ARRAY_ARG(Key)) +{ + return getitem(object(target), object(key)); +} + + +template <class Key, class Value> +void setitem(object const& target, Key const& key, Value const& value BOOST_PYTHON_NO_ARRAY_ARG(Key)) +{ + setitem(target, object(key), object(value)); +} + +template <class Key> +void delitem(object const& target, Key const& key BOOST_PYTHON_NO_ARRAY_ARG(Key)) +{ + delitem(target, object(key)); +} + +template <class Target, class Begin, class End> +object getslice(Target const& target, Begin const& begin, End const& end) +{ + return getslice(object(target), object(begin), object(end)); +} + +template <class Begin, class End, class Value> +void setslice(object const& target, Begin const& begin, End const& end, Value const& value) +{ + setslice(target, object(begin), object(end), object(value)); +} + +template <class Begin, class End> +void delslice(object const& target, Begin const& begin, End const& end) +{ + delslice(target, object(begin), object(end)); +} + +}}} // namespace boost::python::api + +#endif // OBJECT_PROTOCOL_DWA2002615_HPP diff --git a/boost/python/object_protocol_core.hpp b/boost/python/object_protocol_core.hpp new file mode 100644 index 0000000000..a5bd9afcb4 --- /dev/null +++ b/boost/python/object_protocol_core.hpp @@ -0,0 +1,53 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef OBJECT_PROTOCOL_CORE_DWA2002615_HPP +# define OBJECT_PROTOCOL_CORE_DWA2002615_HPP + +# include <boost/python/detail/prefix.hpp> + +# include <boost/python/handle_fwd.hpp> + +namespace boost { namespace python { + +namespace api +{ + class object; + + BOOST_PYTHON_DECL object getattr(object const& target, object const& key); + BOOST_PYTHON_DECL object getattr(object const& target, object const& key, object const& default_); + BOOST_PYTHON_DECL void setattr(object const& target, object const& key, object const& value); + BOOST_PYTHON_DECL void delattr(object const& target, object const& key); + + // These are defined for efficiency, since attributes are commonly + // accessed through literal strings. + BOOST_PYTHON_DECL object getattr(object const& target, char const* key); + BOOST_PYTHON_DECL object getattr(object const& target, char const* key, object const& default_); + BOOST_PYTHON_DECL void setattr(object const& target, char const* key, object const& value); + BOOST_PYTHON_DECL void delattr(object const& target, char const* key); + + BOOST_PYTHON_DECL object getitem(object const& target, object const& key); + BOOST_PYTHON_DECL void setitem(object const& target, object const& key, object const& value); + BOOST_PYTHON_DECL void delitem(object const& target, object const& key); + + BOOST_PYTHON_DECL object getslice(object const& target, handle<> const& begin, handle<> const& end); + BOOST_PYTHON_DECL void setslice(object const& target, handle<> const& begin, handle<> const& end, object const& value); + BOOST_PYTHON_DECL void delslice(object const& target, handle<> const& begin, handle<> const& end); +} + +using api::getattr; +using api::setattr; +using api::delattr; + +using api::getitem; +using api::setitem; +using api::delitem; + +using api::getslice; +using api::setslice; +using api::delslice; + +}} // namespace boost::python + +#endif // OBJECT_PROTOCOL_CORE_DWA2002615_HPP diff --git a/boost/python/object_slices.hpp b/boost/python/object_slices.hpp new file mode 100644 index 0000000000..748c2e954b --- /dev/null +++ b/boost/python/object_slices.hpp @@ -0,0 +1,148 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef OBJECT_SLICES_DWA2002615_HPP +# define OBJECT_SLICES_DWA2002615_HPP + +# include <boost/python/detail/prefix.hpp> + +# include <boost/python/proxy.hpp> +# include <boost/python/object_core.hpp> +# include <boost/python/object_protocol.hpp> +# include <boost/python/handle.hpp> +# include <utility> + +namespace boost { namespace python { namespace api { + +struct const_slice_policies +{ + typedef std::pair<handle<>, handle<> > key_type; + static object get(object const& target, key_type const& key); +}; + +struct slice_policies : const_slice_policies +{ + static object const& set(object const& target, key_type const& key, object const& value); + static void del(object const& target, key_type const& key); +}; + +template <class T, class U> +inline slice_policies::key_type slice_key(T x, U y) +{ + return slice_policies::key_type(handle<>(x), handle<>(y)); +} + +// +// implementation +// +template <class U> +object_slice +object_operators<U>::slice(object_cref start, object_cref finish) +{ + object_cref2 x = *static_cast<U*>(this); + return object_slice(x, api::slice_key(borrowed(start.ptr()), borrowed(finish.ptr()))); +} + +template <class U> +const_object_slice +object_operators<U>::slice(object_cref start, object_cref finish) const +{ + object_cref2 x = *static_cast<U const*>(this); + return const_object_slice(x, api::slice_key(borrowed(start.ptr()), borrowed(finish.ptr()))); +} + +template <class U> +object_slice +object_operators<U>::slice(slice_nil, object_cref finish) +{ + object_cref2 x = *static_cast<U*>(this); + return object_slice(x, api::slice_key(allow_null((PyObject*)0), borrowed(finish.ptr()))); +} + +template <class U> +const_object_slice +object_operators<U>::slice(slice_nil, object_cref finish) const +{ + object_cref2 x = *static_cast<U const*>(this); + return const_object_slice(x, api::slice_key(allow_null((PyObject*)0), borrowed(finish.ptr()))); +} + +template <class U> +object_slice +object_operators<U>::slice(slice_nil, slice_nil) +{ + object_cref2 x = *static_cast<U*>(this); + return object_slice(x, api::slice_key(allow_null((PyObject*)0), allow_null((PyObject*)0))); +} + +template <class U> +const_object_slice +object_operators<U>::slice(slice_nil, slice_nil) const +{ + object_cref2 x = *static_cast<U const*>(this); + return const_object_slice(x, api::slice_key(allow_null((PyObject*)0), allow_null((PyObject*)0))); +} + +template <class U> +object_slice +object_operators<U>::slice(object_cref start, slice_nil) +{ + object_cref2 x = *static_cast<U*>(this); + return object_slice(x, api::slice_key(borrowed(start.ptr()), allow_null((PyObject*)0))); +} + +template <class U> +const_object_slice +object_operators<U>::slice(object_cref start, slice_nil) const +{ + object_cref2 x = *static_cast<U const*>(this); + return const_object_slice(x, api::slice_key(borrowed(start.ptr()), allow_null((PyObject*)0))); +} +# if !defined(BOOST_MSVC) || BOOST_MSVC > 1300 +template <class U> +template <class T, class V> +inline const_object_slice +object_operators<U>::slice(T const& start, V const& end) const +{ + return this->slice( + typename slice_bound<T>::type(start) + , typename slice_bound<V>::type(end)); +} + +template <class U> +template <class T, class V> +inline object_slice +object_operators<U>::slice(T const& start, V const& end) +{ + return this->slice( + typename slice_bound<T>::type(start) + , typename slice_bound<V>::type(end)); +} +# endif + + +inline object const_slice_policies::get(object const& target, key_type const& key) +{ + return getslice(target, key.first, key.second); +} + +inline object const& slice_policies::set( + object const& target + , key_type const& key + , object const& value) +{ + setslice(target, key.first, key.second, value); + return value; +} + +inline void slice_policies::del( + object const& target + , key_type const& key) +{ + delslice(target, key.first, key.second); +} + +}}} // namespace boost::python::api + +#endif // OBJECT_SLICES_DWA2002615_HPP diff --git a/boost/python/opaque_pointer_converter.hpp b/boost/python/opaque_pointer_converter.hpp new file mode 100644 index 0000000000..10eb4234c8 --- /dev/null +++ b/boost/python/opaque_pointer_converter.hpp @@ -0,0 +1,199 @@ +// Copyright Gottfried Ganßauge 2003..2006. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +/* + * Generic Conversion of opaque C++-pointers to a Python-Wrapper. + */ +# ifndef OPAQUE_POINTER_CONVERTER_HPP_ +# define OPAQUE_POINTER_CONVERTER_HPP_ + +# include <boost/python/detail/prefix.hpp> +# include <boost/python/lvalue_from_pytype.hpp> +# include <boost/python/to_python_converter.hpp> +# include <boost/python/converter/registrations.hpp> +# include <boost/python/detail/dealloc.hpp> +# include <boost/python/detail/none.hpp> +# include <boost/python/type_id.hpp> +# include <boost/python/errors.hpp> + +# include <boost/type_traits/remove_pointer.hpp> +# include <boost/type_traits/is_pointer.hpp> +# include <boost/type_traits/is_void.hpp> + +# include <boost/implicit_cast.hpp> + +# include <boost/mpl/eval_if.hpp> +# include <boost/mpl/identity.hpp> +# include <boost/mpl/assert.hpp> + +// opaque -- +// +// registers to- and from- python conversions for a type Pointee. +// +// Note: +// In addition you need to define specializations for type_id +// on the type pointed to by Pointer using +// BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID(Pointee) +// +// For an example see libs/python/test/opaque.cpp +// +namespace boost { namespace python { + +template <class Pointee> +struct opaque +{ + opaque() + { + if (type_object.tp_name == 0) + { + type_object.tp_name = const_cast<char*>(type_id<Pointee*>().name()); + if (PyType_Ready (&type_object) < 0) + { + throw error_already_set(); + } + + this->register_self(); + } + } + + static opaque instance; +private: + + static void* extract(PyObject* op) + { + return PyObject_TypeCheck(op, &type_object) + ? static_cast<python_instance*>(implicit_cast<void*>(op))->x + : 0 + ; + } + + static PyObject* wrap(void const* px) + { + Pointee* x = *static_cast<Pointee*const*>(px); + + if (x == 0) + return detail::none(); + + if ( python_instance *o = PyObject_New(python_instance, &type_object) ) + { + o->x = x; + return static_cast<PyObject*>(implicit_cast<void*>(o)); + } + else + { + throw error_already_set(); + } + } + + void register_self() + { + converter::registration const *existing = + converter::registry::query (type_id<Pointee*>()); + + if ((existing == 0) || (existing->m_to_python == 0)) + { +#ifndef BOOST_PYTHON_NO_PY_SIGNATURES + converter::registry::insert(&extract, type_id<Pointee>(), &get_pytype); + converter::registry::insert(&wrap, type_id<Pointee*>(), &get_pytype); +#else + converter::registry::insert(&extract, type_id<Pointee>()); + converter::registry::insert(&wrap, type_id<Pointee*>()); +#endif + } + } + + struct python_instance + { + PyObject_HEAD + Pointee* x; + }; + + static PyTypeObject type_object; +#ifndef BOOST_PYTHON_NO_PY_SIGNATURES + static PyTypeObject const *get_pytype(){return &type_object; } +#endif +}; + +template <class Pointee> +opaque<Pointee> opaque<Pointee>::instance; + +template <class Pointee> +PyTypeObject opaque<Pointee>::type_object = +{ + PyVarObject_HEAD_INIT(NULL, 0) + 0, + sizeof( BOOST_DEDUCED_TYPENAME opaque<Pointee>::python_instance ), + 0, + ::boost::python::detail::dealloc, + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_compare */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + 0, /* tp_flags */ + 0, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ + 0, /* tp_free */ + 0, /* tp_is_gc */ + 0, /* tp_bases */ + 0, /* tp_mro */ + 0, /* tp_cache */ + 0, /* tp_subclasses */ + 0, /* tp_weaklist */ +#if PYTHON_API_VERSION >= 1012 + 0 /* tp_del */ +#endif +}; +}} // namespace boost::python + +# if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) + +# define BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID(Pointee) + +# else + +// If you change the below, don't forget to alter the end of type_id.hpp +# define BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID(Pointee) \ + namespace boost { namespace python { \ + template<> \ + inline type_info type_id<Pointee>(BOOST_PYTHON_EXPLICIT_TT_DEF(Pointee)) \ + { \ + return type_info (typeid (Pointee *)); \ + } \ + template<> \ + inline type_info type_id<const volatile Pointee&>( \ + BOOST_PYTHON_EXPLICIT_TT_DEF(const volatile Pointee&)) \ + { \ + return type_info (typeid (Pointee *)); \ + } \ + }} + +# endif + +# endif // OPAQUE_POINTER_CONVERTER_HPP_ diff --git a/boost/python/operators.hpp b/boost/python/operators.hpp new file mode 100644 index 0000000000..ea2be7b98f --- /dev/null +++ b/boost/python/operators.hpp @@ -0,0 +1,374 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef OPERATORS_DWA2002530_HPP +# define OPERATORS_DWA2002530_HPP + +# include <boost/python/detail/prefix.hpp> + +# include <boost/python/def_visitor.hpp> +# include <boost/python/converter/arg_to_python.hpp> +# include <boost/python/detail/operator_id.hpp> +# include <boost/python/detail/not_specified.hpp> +# include <boost/python/back_reference.hpp> +# include <boost/mpl/if.hpp> +# include <boost/mpl/eval_if.hpp> +# include <boost/python/self.hpp> +# include <boost/python/other.hpp> +# include <boost/lexical_cast.hpp> +# include <boost/python/refcount.hpp> +# include <boost/python/detail/unwrap_wrapper.hpp> +# include <string> +# include <complex> + +namespace boost { namespace python { + +namespace detail +{ + // This is essentially the old v1 to_python(). It will be eliminated + // once the public interface for to_python is settled on. + template <class T> + PyObject* convert_result(T const& x) + { + return converter::arg_to_python<T>(x).release(); + } + + // Operator implementation template declarations. The nested apply + // declaration here keeps MSVC6 happy. + template <operator_id> struct operator_l + { + template <class L, class R> struct apply; + }; + + template <operator_id> struct operator_r + { + template <class L, class R> struct apply; + }; + + template <operator_id> struct operator_1 + { + template <class T> struct apply; + }; + + // MSVC6 doesn't want us to do this sort of inheritance on a nested + // class template, so we use this layer of indirection to avoid + // ::template<...> on the nested apply functions below + template <operator_id id, class L, class R> + struct operator_l_inner + : operator_l<id>::template apply<L,R> + {}; + + template <operator_id id, class L, class R> + struct operator_r_inner + : operator_r<id>::template apply<L,R> + {}; + + template <operator_id id, class T> + struct operator_1_inner + : operator_1<id>::template apply<T> + {}; + + // Define three different binary_op templates which take care of + // these cases: + // self op self + // self op R + // L op self + // + // The inner apply metafunction is used to adjust the operator to + // the class type being defined. Inheritance of the outer class is + // simply used to provide convenient access to the operation's + // name(). + + // self op self + template <operator_id id> + struct binary_op : operator_l<id> + { + template <class T> + struct apply : operator_l_inner<id,T,T> + { + }; + }; + + // self op R + template <operator_id id, class R> + struct binary_op_l : operator_l<id> + { + template <class T> + struct apply : operator_l_inner<id,T,R> + { + }; + }; + + // L op self + template <operator_id id, class L> + struct binary_op_r : operator_r<id> + { + template <class T> + struct apply : operator_r_inner<id,L,T> + { + }; + }; + + template <operator_id id> + struct unary_op : operator_1<id> + { + template <class T> + struct apply : operator_1_inner<id,T> + { + }; + }; + + // This type is what actually gets returned from operators used on + // self_t + template <operator_id id, class L = not_specified, class R = not_specified> + struct operator_ + : def_visitor<operator_<id,L,R> > + { + private: + template <class ClassT> + void visit(ClassT& cl) const + { + typedef typename mpl::eval_if< + is_same<L,self_t> + , mpl::if_< + is_same<R,self_t> + , binary_op<id> + , binary_op_l< + id + , BOOST_DEDUCED_TYPENAME unwrap_other<R>::type + > + > + , mpl::if_< + is_same<L,not_specified> + , unary_op<id> + , binary_op_r< + id + , BOOST_DEDUCED_TYPENAME unwrap_other<L>::type + > + > + >::type generator; + + cl.def( + generator::name() + , &generator::template apply< + BOOST_DEDUCED_TYPENAME ClassT::wrapped_type + >::execute + ); + } + + friend class python::def_visitor_access; + }; +} + +# define BOOST_PYTHON_BINARY_OPERATION(id, rid, expr) \ +namespace detail \ +{ \ + template <> \ + struct operator_l<op_##id> \ + { \ + template <class L, class R> \ + struct apply \ + { \ + typedef typename unwrap_wrapper_<L>::type lhs; \ + typedef typename unwrap_wrapper_<R>::type rhs; \ + static PyObject* execute(lhs& l, rhs const& r) \ + { \ + return detail::convert_result(expr); \ + } \ + }; \ + static char const* name() { return "__" #id "__"; } \ + }; \ + \ + template <> \ + struct operator_r<op_##id> \ + { \ + template <class L, class R> \ + struct apply \ + { \ + typedef typename unwrap_wrapper_<L>::type lhs; \ + typedef typename unwrap_wrapper_<R>::type rhs; \ + static PyObject* execute(rhs& r, lhs const& l) \ + { \ + return detail::convert_result(expr); \ + } \ + }; \ + static char const* name() { return "__" #rid "__"; } \ + }; \ +} + +# define BOOST_PYTHON_BINARY_OPERATOR(id, rid, op) \ +BOOST_PYTHON_BINARY_OPERATION(id, rid, l op r) \ +namespace self_ns \ +{ \ + template <class L, class R> \ + inline detail::operator_<detail::op_##id,L,R> \ + operator op(L const&, R const&) \ + { \ + return detail::operator_<detail::op_##id,L,R>(); \ + } \ +} + +BOOST_PYTHON_BINARY_OPERATOR(add, radd, +) +BOOST_PYTHON_BINARY_OPERATOR(sub, rsub, -) +BOOST_PYTHON_BINARY_OPERATOR(mul, rmul, *) +#if PY_VERSION_HEX >= 0x03000000 + BOOST_PYTHON_BINARY_OPERATOR(truediv, rtruediv, /) +#else + BOOST_PYTHON_BINARY_OPERATOR(div, rdiv, /) +#endif +BOOST_PYTHON_BINARY_OPERATOR(mod, rmod, %) +BOOST_PYTHON_BINARY_OPERATOR(lshift, rlshift, <<) +BOOST_PYTHON_BINARY_OPERATOR(rshift, rrshift, >>) +BOOST_PYTHON_BINARY_OPERATOR(and, rand, &) +BOOST_PYTHON_BINARY_OPERATOR(xor, rxor, ^) +BOOST_PYTHON_BINARY_OPERATOR(or, ror, |) +BOOST_PYTHON_BINARY_OPERATOR(gt, lt, >) +BOOST_PYTHON_BINARY_OPERATOR(ge, le, >=) +BOOST_PYTHON_BINARY_OPERATOR(lt, gt, <) +BOOST_PYTHON_BINARY_OPERATOR(le, ge, <=) +BOOST_PYTHON_BINARY_OPERATOR(eq, eq, ==) +BOOST_PYTHON_BINARY_OPERATOR(ne, ne, !=) +# undef BOOST_PYTHON_BINARY_OPERATOR + +// pow isn't an operator in C++; handle it specially. +BOOST_PYTHON_BINARY_OPERATION(pow, rpow, pow(l,r)) +# undef BOOST_PYTHON_BINARY_OPERATION + +namespace self_ns +{ +# ifndef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP + template <class L, class R> + inline detail::operator_<detail::op_pow,L,R> + pow(L const&, R const&) + { + return detail::operator_<detail::op_pow,L,R>(); + } +# else + // When there's no argument-dependent lookup, we need these + // overloads to handle the case when everything is imported into the + // global namespace. Note that the plain overload below does /not/ + // take const& arguments. This is needed by MSVC6 at least, or it + // complains of ambiguities, since there's no partial ordering. + inline detail::operator_<detail::op_pow,self_t,self_t> + pow(self_t, self_t) + { + return detail::operator_<detail::op_pow,self_t,self_t>(); + } + template <class R> + inline detail::operator_<detail::op_pow,self_t,R> + pow(self_t const&, R const&) + { + return detail::operator_<detail::op_pow,self_t,R>(); + } + template <class L> + inline detail::operator_<detail::op_pow,L,self_t> + pow(L const&, self_t const&) + { + return detail::operator_<detail::op_pow,L,self_t>(); + } +# endif +} + + +# define BOOST_PYTHON_INPLACE_OPERATOR(id, op) \ +namespace detail \ +{ \ + template <> \ + struct operator_l<op_##id> \ + { \ + template <class L, class R> \ + struct apply \ + { \ + typedef typename unwrap_wrapper_<L>::type lhs; \ + typedef typename unwrap_wrapper_<R>::type rhs; \ + static PyObject* \ + execute(back_reference<lhs&> l, rhs const& r) \ + { \ + l.get() op r; \ + return python::incref(l.source().ptr()); \ + } \ + }; \ + static char const* name() { return "__" #id "__"; } \ + }; \ +} \ +namespace self_ns \ +{ \ + template <class R> \ + inline detail::operator_<detail::op_##id,self_t,R> \ + operator op(self_t const&, R const&) \ + { \ + return detail::operator_<detail::op_##id,self_t,R>(); \ + } \ +} + +BOOST_PYTHON_INPLACE_OPERATOR(iadd,+=) +BOOST_PYTHON_INPLACE_OPERATOR(isub,-=) +BOOST_PYTHON_INPLACE_OPERATOR(imul,*=) +BOOST_PYTHON_INPLACE_OPERATOR(idiv,/=) +BOOST_PYTHON_INPLACE_OPERATOR(imod,%=) +BOOST_PYTHON_INPLACE_OPERATOR(ilshift,<<=) +BOOST_PYTHON_INPLACE_OPERATOR(irshift,>>=) +BOOST_PYTHON_INPLACE_OPERATOR(iand,&=) +BOOST_PYTHON_INPLACE_OPERATOR(ixor,^=) +BOOST_PYTHON_INPLACE_OPERATOR(ior,|=) + +# define BOOST_PYTHON_UNARY_OPERATOR(id, op, func_name) \ +namespace detail \ +{ \ + template <> \ + struct operator_1<op_##id> \ + { \ + template <class T> \ + struct apply \ + { \ + typedef typename unwrap_wrapper_<T>::type self_t; \ + static PyObject* execute(self_t& x) \ + { \ + return detail::convert_result(op(x)); \ + } \ + }; \ + static char const* name() { return "__" #id "__"; } \ + }; \ +} \ +namespace self_ns \ +{ \ + inline detail::operator_<detail::op_##id> \ + func_name(self_t const&) \ + { \ + return detail::operator_<detail::op_##id>(); \ + } \ +} +# undef BOOST_PYTHON_INPLACE_OPERATOR + +BOOST_PYTHON_UNARY_OPERATOR(neg, -, operator-) +BOOST_PYTHON_UNARY_OPERATOR(pos, +, operator+) +BOOST_PYTHON_UNARY_OPERATOR(abs, abs, abs) +BOOST_PYTHON_UNARY_OPERATOR(invert, ~, operator~) +#if PY_VERSION_HEX >= 0x03000000 +BOOST_PYTHON_UNARY_OPERATOR(bool, !!, operator!) +#else +BOOST_PYTHON_UNARY_OPERATOR(nonzero, !!, operator!) +#endif +BOOST_PYTHON_UNARY_OPERATOR(int, long, int_) +BOOST_PYTHON_UNARY_OPERATOR(long, PyLong_FromLong, long_) +BOOST_PYTHON_UNARY_OPERATOR(float, double, float_) +BOOST_PYTHON_UNARY_OPERATOR(complex, std::complex<double>, complex_) +BOOST_PYTHON_UNARY_OPERATOR(str, lexical_cast<std::string>, str) +BOOST_PYTHON_UNARY_OPERATOR(repr, lexical_cast<std::string>, repr) +# undef BOOST_PYTHON_UNARY_OPERATOR + +}} // namespace boost::python + +# ifdef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP +using boost::python::self_ns::abs; +using boost::python::self_ns::int_; +using boost::python::self_ns::long_; +using boost::python::self_ns::float_; +using boost::python::self_ns::complex_; +using boost::python::self_ns::str; +using boost::python::self_ns::repr; +using boost::python::self_ns::pow; +# endif + +#endif // OPERATORS_DWA2002530_HPP diff --git a/boost/python/other.hpp b/boost/python/other.hpp new file mode 100644 index 0000000000..eeece99b7d --- /dev/null +++ b/boost/python/other.hpp @@ -0,0 +1,114 @@ +#ifndef OTHER_DWA20020601_HPP +# define OTHER_DWA20020601_HPP + +# include <boost/python/detail/prefix.hpp> +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +# if _MSC_VER+0 >= 1020 +# pragma once +# endif + +# include <boost/config.hpp> + +namespace boost { namespace python { + +template<class T> struct other +{ + typedef T type; +}; + +# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +namespace detail +{ + template<typename T> + class is_other + { + public: + BOOST_STATIC_CONSTANT(bool, value = false); + }; + + template<typename T> + class is_other<other<T> > + { + public: + BOOST_STATIC_CONSTANT(bool, value = true); + }; + + template<typename T> + class unwrap_other + { + public: + typedef T type; + }; + + template<typename T> + class unwrap_other<other<T> > + { + public: + typedef T type; + }; +} +# else // no partial specialization + +}} // namespace boost::python + +#include <boost/type.hpp> + +namespace boost { namespace python { + +namespace detail +{ + typedef char (&yes_other_t)[1]; + typedef char (&no_other_t)[2]; + + no_other_t is_other_test(...); + + template<typename T> + yes_other_t is_other_test(type< other<T> >); + + template<bool wrapped> + struct other_unwrapper + { + template <class T> + struct apply + { + typedef T type; + }; + }; + + template<> + struct other_unwrapper<true> + { + template <class T> + struct apply + { + typedef typename T::type type; + }; + }; + + template<typename T> + class is_other + { + public: + BOOST_STATIC_CONSTANT( + bool, value = ( + sizeof(detail::is_other_test(type<T>())) + == sizeof(detail::yes_other_t))); + }; + + template <typename T> + class unwrap_other + : public detail::other_unwrapper< + is_other<T>::value + >::template apply<T> + {}; +} + +# endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + +}} // namespace boost::python + +#endif // #ifndef OTHER_DWA20020601_HPP diff --git a/boost/python/overloads.hpp b/boost/python/overloads.hpp new file mode 100644 index 0000000000..e60dc1798e --- /dev/null +++ b/boost/python/overloads.hpp @@ -0,0 +1,13 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef OVERLOADS_DWA2002101_HPP +# define OVERLOADS_DWA2002101_HPP + +# include <boost/python/detail/prefix.hpp> + +# include <boost/python/detail/overloads_fwd.hpp> +# include <boost/python/detail/defaults_def.hpp> + +#endif // OVERLOADS_DWA2002101_HPP diff --git a/boost/python/override.hpp b/boost/python/override.hpp new file mode 100644 index 0000000000..39714257f9 --- /dev/null +++ b/boost/python/override.hpp @@ -0,0 +1,144 @@ +#if !defined(BOOST_PP_IS_ITERATING) + +// Copyright David Abrahams 2004. Distributed under the Boost +// Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +#ifndef OVERRIDE_DWA2004721_HPP +# define OVERRIDE_DWA2004721_HPP + +# include <boost/python/detail/prefix.hpp> + +# include <boost/python/converter/return_from_python.hpp> + +# include <boost/python/extract.hpp> +# include <boost/python/handle.hpp> + +# include <boost/preprocessor/iterate.hpp> +# include <boost/preprocessor/repeat.hpp> +# include <boost/preprocessor/debug/line.hpp> +# include <boost/preprocessor/repetition/enum_params.hpp> +# include <boost/preprocessor/repetition/enum_binary_params.hpp> + +# include <boost/type.hpp> + +namespace boost { namespace python { + +class override; + +namespace detail +{ + class wrapper_base; + + // The result of calling a method. + class method_result + { + private: + friend class boost::python::override; + explicit method_result(PyObject* x) + : m_obj(x) + {} + + public: + template <class T> + operator T() + { + converter::return_from_python<T> converter; + return converter(m_obj.release()); + } + +# if BOOST_WORKAROUND(_MSC_FULL_VER, BOOST_TESTED_AT(140050215)) + template <class T> + operator T*() + { + converter::return_from_python<T*> converter; + return converter(m_obj.release()); + } +# endif + +# if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1400)) || BOOST_WORKAROUND(BOOST_INTEL_WIN, >= 900) + // No operator T& +# else + + template <class T> + operator T&() const + { + converter::return_from_python<T&> converter; + return converter(const_cast<handle<>&>(m_obj).release()); + } +# endif + + template <class T> + T as(type<T>* = 0) + { + converter::return_from_python<T> converter; + return converter(m_obj.release()); + } + + template <class T> + T unchecked(type<T>* = 0) + { + return extract<T>(m_obj.get())(); + } + private: + mutable handle<> m_obj; + }; +} + +class override : public object +{ + private: + friend class detail::wrapper_base; + override(handle<> x) + : object(x) + {} + + public: + detail::method_result + operator()() const + { + detail::method_result x( + PyEval_CallFunction( + this->ptr() + , const_cast<char*>("()") + )); + return x; + } + +# define BOOST_PYTHON_fast_arg_to_python_get(z, n, _) \ + , converter::arg_to_python<A##n>(a##n).get() + +# define BOOST_PP_ITERATION_PARAMS_1 (3, (1, BOOST_PYTHON_MAX_ARITY, <boost/python/override.hpp>)) +# include BOOST_PP_ITERATE() + +# undef BOOST_PYTHON_fast_arg_to_python_get +}; + +}} // namespace boost::python + +#endif // OVERRIDE_DWA2004721_HPP + +#else +# if !(BOOST_WORKAROUND(__MWERKS__, > 0x3100) \ + && BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3201))) +# line BOOST_PP_LINE(__LINE__, override.hpp) +# endif + +# define N BOOST_PP_ITERATION() + +template < + BOOST_PP_ENUM_PARAMS_Z(1, N, class A) + > +detail::method_result +operator()( BOOST_PP_ENUM_BINARY_PARAMS_Z(1, N, A, const& a) ) const +{ + detail::method_result x( + PyEval_CallFunction( + this->ptr() + , const_cast<char*>("(" BOOST_PP_REPEAT_1ST(N, BOOST_PYTHON_FIXED, "O") ")") + BOOST_PP_REPEAT_1ST(N, BOOST_PYTHON_fast_arg_to_python_get, nil) + )); + return x; +} + +# undef N +#endif diff --git a/boost/python/pointee.hpp b/boost/python/pointee.hpp new file mode 100644 index 0000000000..ab8bb87439 --- /dev/null +++ b/boost/python/pointee.hpp @@ -0,0 +1,43 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef POINTEE_DWA2002323_HPP +# define POINTEE_DWA2002323_HPP + +# include <boost/python/detail/prefix.hpp> + +# include <boost/type_traits/object_traits.hpp> +# include <boost/type_traits/remove_pointer.hpp> + +namespace boost { namespace python { + +namespace detail +{ + template <bool is_ptr = true> + struct pointee_impl + { + template <class T> struct apply : remove_pointer<T> {}; + }; + + template <> + struct pointee_impl<false> + { + template <class T> struct apply + { + typedef typename T::element_type type; + }; + }; +} + +template <class T> +struct pointee + : detail::pointee_impl< + ::boost::is_pointer<T>::value + >::template apply<T> +{ +}; + +}} // namespace boost::python::detail + +#endif // POINTEE_DWA2002323_HPP diff --git a/boost/python/proxy.hpp b/boost/python/proxy.hpp new file mode 100644 index 0000000000..a956eac1cc --- /dev/null +++ b/boost/python/proxy.hpp @@ -0,0 +1,101 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef PROXY_DWA2002615_HPP +# define PROXY_DWA2002615_HPP +# include <boost/python/detail/prefix.hpp> +# include <boost/python/object_core.hpp> +# include <boost/python/object_operators.hpp> + +namespace boost { namespace python { namespace api { + +template <class Policies> +class proxy : public object_operators<proxy<Policies> > +{ + typedef typename Policies::key_type key_type; + +# if !defined(BOOST_MSVC) || BOOST_MSVC >= 1300 + typedef proxy const& assignment_self; +# else + typedef proxy assignment_self; +# endif + public: + proxy(object const& target, key_type const& key); + operator object() const; + + // to support a[b] = c[d] + proxy const& operator=(assignment_self) const; + + template <class T> + inline proxy const& operator=(T const& rhs) const + { + Policies::set(m_target, m_key, object(rhs)); + return *this; + } + + public: // implementation detail + void del() const; + + private: + object m_target; + key_type m_key; +}; + + +template <class T> +inline void del(proxy<T> const& x) +{ + x.del(); +} + +// +// implementation +// + +template <class Policies> +inline proxy<Policies>::proxy(object const& target, key_type const& key) + : m_target(target), m_key(key) +{} + +template <class Policies> +inline proxy<Policies>::operator object() const +{ + return Policies::get(m_target, m_key); +} + +// to support a[b] = c[d] +template <class Policies> +inline proxy<Policies> const& proxy<Policies>::operator=(typename proxy::assignment_self rhs) const +{ + return *this = python::object(rhs); +} + +# define BOOST_PYTHON_PROXY_INPLACE(op) \ +template <class Policies, class R> \ +proxy<Policies> const& operator op(proxy<Policies> const& lhs, R const& rhs) \ +{ \ + object old(lhs); \ + return lhs = (old op rhs); \ +} +BOOST_PYTHON_PROXY_INPLACE(+=) +BOOST_PYTHON_PROXY_INPLACE(-=) +BOOST_PYTHON_PROXY_INPLACE(*=) +BOOST_PYTHON_PROXY_INPLACE(/=) +BOOST_PYTHON_PROXY_INPLACE(%=) +BOOST_PYTHON_PROXY_INPLACE(<<=) +BOOST_PYTHON_PROXY_INPLACE(>>=) +BOOST_PYTHON_PROXY_INPLACE(&=) +BOOST_PYTHON_PROXY_INPLACE(^=) +BOOST_PYTHON_PROXY_INPLACE(|=) +# undef BOOST_PYTHON_PROXY_INPLACE + +template <class Policies> +inline void proxy<Policies>::del() const +{ + Policies::del(m_target, m_key); +} + +}}} // namespace boost::python::api + +#endif // PROXY_DWA2002615_HPP diff --git a/boost/python/ptr.hpp b/boost/python/ptr.hpp new file mode 100644 index 0000000000..af1339c426 --- /dev/null +++ b/boost/python/ptr.hpp @@ -0,0 +1,128 @@ +#ifndef PTR_DWA20020601_HPP +# define PTR_DWA20020601_HPP + +# include <boost/python/detail/prefix.hpp> +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// Based on boost/ref.hpp, thus: +// Copyright (C) 1999, 2000 Jaakko Jarvi (jaakko.jarvi@cs.utu.fi) +// Copyright (C) 2001 Peter Dimov + +# if _MSC_VER+0 >= 1020 +# pragma once +# endif + +# include <boost/config.hpp> +# include <boost/mpl/bool.hpp> + +namespace boost { namespace python { + +template<class Ptr> class pointer_wrapper +{ + public: + typedef Ptr type; + + explicit pointer_wrapper(Ptr x): p_(x) {} + operator Ptr() const { return p_; } + Ptr get() const { return p_; } + private: + Ptr p_; +}; + +template<class T> +inline pointer_wrapper<T> ptr(T t) +{ + return pointer_wrapper<T>(t); +} + +# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +template<typename T> +class is_pointer_wrapper + : public mpl::false_ +{ +}; + +template<typename T> +class is_pointer_wrapper<pointer_wrapper<T> > + : public mpl::true_ +{ +}; + +template<typename T> +class unwrap_pointer +{ + public: + typedef T type; +}; + +template<typename T> +class unwrap_pointer<pointer_wrapper<T> > +{ + public: + typedef T type; +}; +# else // no partial specialization + +}} // namespace boost::python + +#include <boost/type.hpp> + +namespace boost { namespace python { + +namespace detail +{ + typedef char (&yes_pointer_wrapper_t)[1]; + typedef char (&no_pointer_wrapper_t)[2]; + + no_pointer_wrapper_t is_pointer_wrapper_test(...); + + template<typename T> + yes_pointer_wrapper_t is_pointer_wrapper_test(boost::type< pointer_wrapper<T> >); + + template<bool wrapped> + struct pointer_unwrapper + { + template <class T> + struct apply + { + typedef T type; + }; + }; + + template<> + struct pointer_unwrapper<true> + { + template <class T> + struct apply + { + typedef typename T::type type; + }; + }; +} + +template<typename T> +class is_pointer_wrapper +{ + public: + BOOST_STATIC_CONSTANT( + bool, value = ( + sizeof(detail::is_pointer_wrapper_test(boost::type<T>())) + == sizeof(detail::yes_pointer_wrapper_t))); + typedef mpl::bool_<value> type; +}; + +template <typename T> +class unwrap_pointer + : public detail::pointer_unwrapper< + is_pointer_wrapper<T>::value + >::template apply<T> +{}; + +# endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + +}} // namespace boost::python + +#endif // #ifndef PTR_DWA20020601_HPP diff --git a/boost/python/pure_virtual.hpp b/boost/python/pure_virtual.hpp new file mode 100644 index 0000000000..b3b34ffcdb --- /dev/null +++ b/boost/python/pure_virtual.hpp @@ -0,0 +1,124 @@ +// Copyright David Abrahams 2003. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef PURE_VIRTUAL_DWA2003810_HPP +# define PURE_VIRTUAL_DWA2003810_HPP + +# include <boost/python/def_visitor.hpp> +# include <boost/python/default_call_policies.hpp> +# include <boost/mpl/push_front.hpp> +# include <boost/mpl/pop_front.hpp> + +# include <boost/python/detail/nullary_function_adaptor.hpp> + +namespace boost { namespace python { + +namespace detail +{ + // + // @group Helpers for pure_virtual_visitor. { + // + + // Raises a Python RuntimeError reporting that a pure virtual + // function was called. + void BOOST_PYTHON_DECL pure_virtual_called(); + + // Replace the two front elements of S with T1 and T2 + template <class S, class T1, class T2> + struct replace_front2 + { + // Metafunction forwarding seemed to confound vc6 + typedef typename mpl::push_front< + typename mpl::push_front< + typename mpl::pop_front< + typename mpl::pop_front< + S + >::type + >::type + , T2 + >::type + , T1 + >::type type; + }; + + // Given an MPL sequence representing a member function [object] + // signature, returns a new MPL sequence whose return type is + // replaced by void, and whose first argument is replaced by C&. + template <class C, class S> + typename replace_front2<S,void,C&>::type + error_signature(S BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(C)) + { + typedef typename replace_front2<S,void,C&>::type r; + return r(); + } + + // + // } + // + + // + // A def_visitor which defines a method as usual, then adds a + // corresponding function which raises a "pure virtual called" + // exception unless it's been overridden. + // + template <class PointerToMemberFunction> + struct pure_virtual_visitor + : def_visitor<pure_virtual_visitor<PointerToMemberFunction> > + { + pure_virtual_visitor(PointerToMemberFunction pmf) + : m_pmf(pmf) + {} + + private: + friend class python::def_visitor_access; + + template <class C_, class Options> + void visit(C_& c, char const* name, Options& options) const + { + // This should probably be a nicer error message + BOOST_STATIC_ASSERT(!Options::has_default_implementation); + + // Add the virtual function dispatcher + c.def( + name + , m_pmf + , options.doc() + , options.keywords() + , options.policies() + ); + + typedef BOOST_DEDUCED_TYPENAME C_::metadata::held_type held_type; + + // Add the default implementation which raises the exception + c.def( + name + , make_function( + detail::nullary_function_adaptor<void(*)()>(pure_virtual_called) + , default_call_policies() + , detail::error_signature<held_type>(detail::get_signature(m_pmf)) + ) + ); + } + + private: // data members + PointerToMemberFunction m_pmf; + }; +} + +// +// Passed a pointer to member function, generates a def_visitor which +// creates a method that only dispatches to Python if the function has +// been overridden, either in C++ or in Python, raising a "pure +// virtual called" exception otherwise. +// +template <class PointerToMemberFunction> +detail::pure_virtual_visitor<PointerToMemberFunction> +pure_virtual(PointerToMemberFunction pmf) +{ + return detail::pure_virtual_visitor<PointerToMemberFunction>(pmf); +} + +}} // namespace boost::python + +#endif // PURE_VIRTUAL_DWA2003810_HPP diff --git a/boost/python/raw_function.hpp b/boost/python/raw_function.hpp new file mode 100644 index 0000000000..9d9f6b8b1b --- /dev/null +++ b/boost/python/raw_function.hpp @@ -0,0 +1,61 @@ +// Copyright David Abrahams 2003. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef RAW_FUNCTION_DWA200336_HPP +# define RAW_FUNCTION_DWA200336_HPP + +# include <boost/python/detail/prefix.hpp> + +# include <boost/python/tuple.hpp> +# include <boost/python/dict.hpp> +# include <boost/python/object/py_function.hpp> +# include <boost/mpl/vector/vector10.hpp> + +# include <boost/limits.hpp> +# include <cstddef> + +namespace boost { namespace python { + +namespace detail +{ + template <class F> + struct raw_dispatcher + { + raw_dispatcher(F f) : f(f) {} + + PyObject* operator()(PyObject* args, PyObject* keywords) + { + return incref( + object( + f( + tuple(borrowed_reference(args)) + , keywords ? dict(borrowed_reference(keywords)) : dict() + ) + ).ptr() + ); + } + + private: + F f; + }; + + object BOOST_PYTHON_DECL make_raw_function(objects::py_function); +} + +template <class F> +object raw_function(F f, std::size_t min_args = 0) +{ + return detail::make_raw_function( + objects::py_function( + detail::raw_dispatcher<F>(f) + , mpl::vector1<PyObject*>() + , min_args + , (std::numeric_limits<unsigned>::max)() + ) + ); +} + +}} // namespace boost::python + +#endif // RAW_FUNCTION_DWA200336_HPP diff --git a/boost/python/refcount.hpp b/boost/python/refcount.hpp new file mode 100644 index 0000000000..5ba5433c22 --- /dev/null +++ b/boost/python/refcount.hpp @@ -0,0 +1,41 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef REFCOUNT_DWA2002615_HPP +# define REFCOUNT_DWA2002615_HPP + +# include <boost/python/detail/prefix.hpp> +# include <boost/python/cast.hpp> + +namespace boost { namespace python { + +template <class T> +inline T* incref(T* p) +{ + Py_INCREF(python::upcast<PyObject>(p)); + return p; +} + +template <class T> +inline T* xincref(T* p) +{ + Py_XINCREF(python::upcast<PyObject>(p)); + return p; +} + +template <class T> +inline void decref(T* p) +{ + Py_DECREF(python::upcast<PyObject>(p)); +} + +template <class T> +inline void xdecref(T* p) +{ + Py_XDECREF(python::upcast<PyObject>(p)); +} + +}} // namespace boost::python + +#endif // REFCOUNT_DWA2002615_HPP diff --git a/boost/python/reference_existing_object.hpp b/boost/python/reference_existing_object.hpp new file mode 100644 index 0000000000..bb8ddf7380 --- /dev/null +++ b/boost/python/reference_existing_object.hpp @@ -0,0 +1,46 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef REFERENCE_EXISTING_OBJECT_DWA200222_HPP +# define REFERENCE_EXISTING_OBJECT_DWA200222_HPP + +# include <boost/python/detail/prefix.hpp> +# include <boost/python/detail/indirect_traits.hpp> +# include <boost/mpl/if.hpp> +# include <boost/python/to_python_indirect.hpp> +# include <boost/type_traits/composite_traits.hpp> + +namespace boost { namespace python { + +namespace detail +{ + template <class R> + struct reference_existing_object_requires_a_pointer_or_reference_return_type +# if defined(__GNUC__) && __GNUC__ >= 3 || defined(__EDG__) + {} +# endif + ; +} + +template <class T> struct to_python_value; + +struct reference_existing_object +{ + template <class T> + struct apply + { + BOOST_STATIC_CONSTANT( + bool, ok = is_pointer<T>::value || is_reference<T>::value); + + typedef typename mpl::if_c< + ok + , to_python_indirect<T, detail::make_reference_holder> + , detail::reference_existing_object_requires_a_pointer_or_reference_return_type<T> + >::type type; + }; +}; + +}} // namespace boost::python + +#endif // REFERENCE_EXISTING_OBJECT_DWA200222_HPP diff --git a/boost/python/register_ptr_to_python.hpp b/boost/python/register_ptr_to_python.hpp new file mode 100644 index 0000000000..7a22fe5052 --- /dev/null +++ b/boost/python/register_ptr_to_python.hpp @@ -0,0 +1,31 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef REGISTER_PTR_TO_PYTHON_HPP +#define REGISTER_PTR_TO_PYTHON_HPP + +#include <boost/python/pointee.hpp> +#include <boost/python/object.hpp> +#include <boost/python/object/class_wrapper.hpp> + +namespace boost { namespace python { + +template <class P> +void register_ptr_to_python(BOOST_EXPLICIT_TEMPLATE_TYPE(P)) +{ + typedef typename boost::python::pointee<P>::type X; + objects::class_value_wrapper< + P + , objects::make_ptr_instance< + X + , objects::pointer_holder<P,X> + > + >(); +} + +}} // namespace boost::python + +#endif // REGISTER_PTR_TO_PYTHON_HPP + + diff --git a/boost/python/return_arg.hpp b/boost/python/return_arg.hpp new file mode 100644 index 0000000000..c36f898d7d --- /dev/null +++ b/boost/python/return_arg.hpp @@ -0,0 +1,110 @@ +// Copyright David Abrahams and Nikolay Mladenov 2003. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef RETURN_ARG_DWA2003719_HPP +# define RETURN_ARG_DWA2003719_HPP +# include <boost/python/default_call_policies.hpp> +# include <boost/python/detail/none.hpp> +# include <boost/python/detail/value_arg.hpp> + +#ifndef BOOST_PYTHON_NO_PY_SIGNATURES +# include <boost/python/converter/pytype_function.hpp> +#endif + +# include <boost/type_traits/add_reference.hpp> +# include <boost/type_traits/add_const.hpp> + +# include <boost/mpl/int.hpp> +# include <boost/mpl/at.hpp> + +# include <boost/static_assert.hpp> +# include <boost/python/refcount.hpp> + +# include <cstddef> + +namespace boost { namespace python { + +namespace detail +{ + template <std::size_t> + struct return_arg_pos_argument_must_be_positive +# if defined(__GNUC__) && __GNUC__ >= 3 || defined(__EDG__) + {} +# endif + ; + + struct return_none + { + template <class T> struct apply + { + struct type + { + static bool convertible() + { + return true; + } + + PyObject *operator()( typename value_arg<T>::type ) const + { + return none(); + } +#ifndef BOOST_PYTHON_NO_PY_SIGNATURES + PyTypeObject const *get_pytype() const { return converter::expected_pytype_for_arg<T>::get_pytype() ; } +#endif + }; + }; + }; +} + +template < + std::size_t arg_pos=1 + , class Base = default_call_policies +> +struct return_arg : Base +{ + private: + BOOST_STATIC_CONSTANT(bool, legal = arg_pos > 0); + + public: + typedef typename mpl::if_c< + legal + , detail::return_none + , detail::return_arg_pos_argument_must_be_positive<arg_pos> + // we could default to the base result_converter in case or + // arg_pos==0 since return arg 0 means return result, but I + // think it is better to issue an error instead, cause it can + // lead to confusions + >::type result_converter; + + template <class ArgumentPackage> + static PyObject* postcall(ArgumentPackage const& args, PyObject* result) + { + // In case of arg_pos == 0 we could simply return Base::postcall, + // but this is redundant + BOOST_STATIC_ASSERT(arg_pos > 0); + + result = Base::postcall(args,result); + if (!result) + return 0; + Py_DECREF(result); + return incref( detail::get(mpl::int_<arg_pos-1>(),args) ); + } + + template <class Sig> + struct extract_return_type : mpl::at_c<Sig, arg_pos> + { + }; + +}; + +template < + class Base = default_call_policies + > +struct return_self + : return_arg<1,Base> +{}; + +}} // namespace boost::python + +#endif // RETURN_ARG_DWA2003719_HPP diff --git a/boost/python/return_by_value.hpp b/boost/python/return_by_value.hpp new file mode 100644 index 0000000000..593fc59cfe --- /dev/null +++ b/boost/python/return_by_value.hpp @@ -0,0 +1,31 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef BY_VALUE_DWA20021015_HPP +# define BY_VALUE_DWA20021015_HPP + +# include <boost/python/detail/prefix.hpp> + +# include <boost/python/to_python_value.hpp> +# include <boost/type_traits/add_reference.hpp> +# include <boost/type_traits/add_const.hpp> + +# include <boost/python/detail/value_arg.hpp> + +namespace boost { namespace python { + +struct return_by_value +{ + template <class R> + struct apply + { + typedef to_python_value< + typename detail::value_arg<R>::type + > type; + }; +}; + +}} // namespace boost::python + +#endif // BY_VALUE_DWA20021015_HPP diff --git a/boost/python/return_internal_reference.hpp b/boost/python/return_internal_reference.hpp new file mode 100644 index 0000000000..acb89e6dc8 --- /dev/null +++ b/boost/python/return_internal_reference.hpp @@ -0,0 +1,43 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef RETURN_INTERNAL_REFERENCE_DWA2002131_HPP +# define RETURN_INTERNAL_REFERENCE_DWA2002131_HPP + +# include <boost/python/detail/prefix.hpp> + +# include <boost/python/default_call_policies.hpp> +# include <boost/python/reference_existing_object.hpp> +# include <boost/python/with_custodian_and_ward.hpp> +# include <boost/mpl/if.hpp> + +namespace boost { namespace python { + +namespace detail +{ + template <std::size_t> + struct return_internal_reference_owner_arg_must_be_greater_than_zero +# if defined(__GNUC__) && __GNUC__ >= 3 || defined(__EDG__) + {} +# endif + ; +} + +template <std::size_t owner_arg = 1, class BasePolicy_ = default_call_policies> +struct return_internal_reference + : with_custodian_and_ward_postcall<0, owner_arg, BasePolicy_> +{ + private: + BOOST_STATIC_CONSTANT(bool, legal = owner_arg > 0); + public: + typedef typename mpl::if_c< + legal + , reference_existing_object + , detail::return_internal_reference_owner_arg_must_be_greater_than_zero<owner_arg> + >::type result_converter; +}; + +}} // namespace boost::python + +#endif // RETURN_INTERNAL_REFERENCE_DWA2002131_HPP diff --git a/boost/python/return_opaque_pointer.hpp b/boost/python/return_opaque_pointer.hpp new file mode 100644 index 0000000000..cf544d8030 --- /dev/null +++ b/boost/python/return_opaque_pointer.hpp @@ -0,0 +1,47 @@ +// Copyright Gottfried Ganßauge 2003. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +/* + * Generic Return value converter generator for opaque C++-pointers + */ +# ifndef RETURN_OPAQUE_POINTER_HPP_ +# define RETURN_OPAQUE_POINTER_HPP_ + +# include <boost/python/detail/prefix.hpp> +# include <boost/python/opaque_pointer_converter.hpp> +# include <boost/python/detail/force_instantiate.hpp> +# include <boost/python/to_python_value.hpp> +# include <boost/python/detail/value_arg.hpp> +# include <boost/mpl/assert.hpp> + +namespace boost { namespace python { + +namespace detail +{ + template <class Pointee> + static void opaque_pointee(Pointee const volatile*) + { + force_instantiate(opaque<Pointee>::instance); + } +} + +struct return_opaque_pointer +{ + template <class R> + struct apply + { + BOOST_MPL_ASSERT_MSG( is_pointer<R>::value, RETURN_OPAQUE_POINTER_EXPECTS_A_POINTER_TYPE, (R)); + + struct type : + boost::python::to_python_value< + typename detail::value_arg<R>::type + > + { + type() { detail::opaque_pointee(R()); } + }; + }; +}; + +}} // namespace boost::python +# endif // RETURN_OPAQUE_POINTER_HPP_ diff --git a/boost/python/return_value_policy.hpp b/boost/python/return_value_policy.hpp new file mode 100644 index 0000000000..9a5fba380b --- /dev/null +++ b/boost/python/return_value_policy.hpp @@ -0,0 +1,21 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef RETURN_VALUE_POLICY_DWA2002131_HPP +# define RETURN_VALUE_POLICY_DWA2002131_HPP + +# include <boost/python/detail/prefix.hpp> +# include <boost/python/default_call_policies.hpp> + +namespace boost { namespace python { + +template <class ResultConverterGenerator, class BasePolicy_ = default_call_policies> +struct return_value_policy : BasePolicy_ +{ + typedef ResultConverterGenerator result_converter; +}; + +}} // namespace boost::python + +#endif // RETURN_VALUE_POLICY_DWA2002131_HPP diff --git a/boost/python/scope.hpp b/boost/python/scope.hpp new file mode 100644 index 0000000000..ae9a40a383 --- /dev/null +++ b/boost/python/scope.hpp @@ -0,0 +1,78 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef SCOPE_DWA2002724_HPP +# define SCOPE_DWA2002724_HPP + +# include <boost/python/detail/prefix.hpp> +# include <boost/python/object.hpp> +# include <boost/python/refcount.hpp> +# include <boost/utility.hpp> + +namespace boost { namespace python { + +namespace detail +{ + // Making this a namespace-scope variable to avoid Cygwin issues. + // Use a PyObject* to avoid problems with static destruction after Py_Finalize + extern BOOST_PYTHON_DECL PyObject* current_scope; +} + +class scope + : public object +{ + public: + inline scope(scope const&); + inline scope(object const&); + inline scope(); + inline ~scope(); + + private: // data members + PyObject* m_previous_scope; + + private: // unimplemented functions + void operator=(scope const&); +}; + +inline scope::scope(object const& new_scope) + : object(new_scope) + , m_previous_scope(detail::current_scope) +{ + detail::current_scope = python::incref(new_scope.ptr()); +} + +inline scope::scope() + : object(detail::borrowed_reference( + detail::current_scope ? detail::current_scope : Py_None + )) + , m_previous_scope(python::xincref(detail::current_scope)) +{ +} + +inline scope::~scope() +{ + python::xdecref(detail::current_scope); + detail::current_scope = m_previous_scope; +} + +namespace converter +{ + template <> + struct object_manager_traits<scope> + : object_manager_traits<object> + { + }; +} + +// Placing this after the specialization above suppresses a CWPro8.3 bug +inline scope::scope(scope const& new_scope) + : object(new_scope) + , m_previous_scope(detail::current_scope) +{ + detail::current_scope = python::incref(new_scope.ptr()); +} + +}} // namespace boost::python + +#endif // SCOPE_DWA2002724_HPP diff --git a/boost/python/self.hpp b/boost/python/self.hpp new file mode 100644 index 0000000000..99ec5b8fbe --- /dev/null +++ b/boost/python/self.hpp @@ -0,0 +1,33 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef SELF_DWA2002531_HPP +# define SELF_DWA2002531_HPP + +# include <boost/python/detail/prefix.hpp> + +namespace boost { namespace python { + +#define BOOST_PYTHON_SELF_IS_CLASS + +// Sink self_t into its own namespace so that we have a safe place to +// put the completely general operator templates which operate on +// it. It is possible to avoid this, but it turns out to be much more +// complicated and finally GCC 2.95.2 chokes on it. +namespace self_ns +{ +# ifndef BOOST_PYTHON_SELF_IS_CLASS + enum self_t { self }; +# else + struct self_t {}; + extern BOOST_PYTHON_DECL self_t self; +# endif +} + +using self_ns::self_t; +using self_ns::self; + +}} // namespace boost::python + +#endif // SELF_DWA2002531_HPP diff --git a/boost/python/signature.hpp b/boost/python/signature.hpp new file mode 100644 index 0000000000..f1143e3abe --- /dev/null +++ b/boost/python/signature.hpp @@ -0,0 +1,252 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright David Abrahams 2002, Joel de Guzman, 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +/////////////////////////////////////////////////////////////////////////////// +#if !defined(BOOST_PP_IS_ITERATING) + +# ifndef SIGNATURE_JDG20020813_HPP +# define SIGNATURE_JDG20020813_HPP + +# include <boost/python/detail/prefix.hpp> + +# include <boost/mpl/if.hpp> +# include <boost/type_traits/is_convertible.hpp> + +# include <boost/python/detail/preprocessor.hpp> +# include <boost/preprocessor/repeat.hpp> +# include <boost/preprocessor/enum.hpp> +# include <boost/preprocessor/enum_params.hpp> +# include <boost/preprocessor/empty.hpp> +# include <boost/preprocessor/arithmetic/sub.hpp> +# include <boost/preprocessor/iterate.hpp> +# include <boost/python/detail/type_list.hpp> + +# include <boost/preprocessor/debug/line.hpp> +# include <boost/preprocessor/arithmetic/sub.hpp> +# include <boost/preprocessor/arithmetic/inc.hpp> +# include <boost/preprocessor/repetition/enum_trailing_params.hpp> + +# define BOOST_PYTHON_LIST_INC(n) \ + BOOST_PP_CAT(mpl::vector, BOOST_PP_INC(n)) + +/////////////////////////////////////////////////////////////////////////////// +namespace boost { namespace python { namespace detail { + +// A metafunction returning C1 if C1 is derived from C2, and C2 +// otherwise +template <class C1, class C2> +struct most_derived +{ + typedef typename mpl::if_< + is_convertible<C1*,C2*> + , C1 + , C2 + >::type type; +}; + +// The following macros generate expansions for:: +// +// template <class RT, class T0... class TN> +// inline mpl::vector<RT, T0...TN> +// get_signature(RT(BOOST_PYTHON_FN_CC *)(T0...TN), void* = 0) +// { +// return mpl::list<RT, T0...TN>(); +// } +// +// where BOOST_PYTHON_FN_CC is a calling convention keyword, can be +// +// empty, for default calling convention +// __cdecl (if BOOST_PYTHON_ENABLE_CDECL is defined) +// __stdcall (if BOOST_PYTHON_ENABLE_STDCALL is defined) +// __fastcall (if BOOST_PYTHON_ENABLE_FASTCALL is defined) +// +// And, for an appropriate assortment of cv-qualifications:: +// +// template <class RT, class ClassT, class T0... class TN> +// inline mpl::vector<RT, ClassT&, T0...TN> +// get_signature(RT(BOOST_PYTHON_FN_CC ClassT::*)(T0...TN) cv)) +// { +// return mpl::list<RT, ClassT&, T0...TN>(); +// } +// +// template <class Target, class RT, class ClassT, class T0... class TN> +// inline mpl::vector< +// RT +// , typename most_derived<Target, ClassT>::type& +// , T0...TN +// > +// get_signature(RT(BOOST_PYTHON_FN_CC ClassT::*)(T0...TN) cv), Target*) +// { +// return mpl::list<RT, ClassT&, T0...TN>(); +// } +// +// There are two forms for invoking get_signature:: +// +// get_signature(f) +// +// and :: +// +// get_signature(f,(Target*)0) +// +// These functions extract the return type, class (for member +// functions) and arguments of the input signature and stuff them in +// an mpl type sequence (the calling convention is dropped). +// Note that cv-qualification is dropped from +// the "hidden this" argument of member functions; that is a +// necessary sacrifice to ensure that an lvalue from_python converter +// is used. A pointer is not used so that None will be rejected for +// overload resolution. +// +// The second form of get_signature essentially downcasts the "hidden +// this" argument of member functions to Target, because the function +// may actually be a member of a base class which is not wrapped, and +// in that case conversion from python would fail. +// +// @group { + +// 'default' calling convention + +# define BOOST_PYTHON_FN_CC + +# define BOOST_PP_ITERATION_PARAMS_1 \ + (3, (0, BOOST_PYTHON_MAX_ARITY, <boost/python/signature.hpp>)) + +# include BOOST_PP_ITERATE() + +# undef BOOST_PYTHON_FN_CC + +// __cdecl calling convention + +# if defined(BOOST_PYTHON_ENABLE_CDECL) + +# define BOOST_PYTHON_FN_CC __cdecl +# define BOOST_PYTHON_FN_CC_IS_CDECL + +# define BOOST_PP_ITERATION_PARAMS_1 \ + (3, (0, BOOST_PYTHON_MAX_ARITY, <boost/python/signature.hpp>)) + +# include BOOST_PP_ITERATE() + +# undef BOOST_PYTHON_FN_CC +# undef BOOST_PYTHON_FN_CC_IS_CDECL + +# endif // defined(BOOST_PYTHON_ENABLE_CDECL) + +// __stdcall calling convention + +# if defined(BOOST_PYTHON_ENABLE_STDCALL) + +# define BOOST_PYTHON_FN_CC __stdcall + +# define BOOST_PP_ITERATION_PARAMS_1 \ + (3, (0, BOOST_PYTHON_MAX_ARITY, <boost/python/signature.hpp>)) + +# include BOOST_PP_ITERATE() + +# undef BOOST_PYTHON_FN_CC + +# endif // defined(BOOST_PYTHON_ENABLE_STDCALL) + +// __fastcall calling convention + +# if defined(BOOST_PYTHON_ENABLE_FASTCALL) + +# define BOOST_PYTHON_FN_CC __fastcall + +# define BOOST_PP_ITERATION_PARAMS_1 \ + (3, (0, BOOST_PYTHON_MAX_ARITY, <boost/python/signature.hpp>)) + +# include BOOST_PP_ITERATE() + +# undef BOOST_PYTHON_FN_CC + +# endif // defined(BOOST_PYTHON_ENABLE_FASTCALL) + +# undef BOOST_PYTHON_LIST_INC + +// } + +}}} // namespace boost::python::detail + + +# endif // SIGNATURE_JDG20020813_HPP + +// For gcc 4.4 compatability, we must include the +// BOOST_PP_ITERATION_DEPTH test inside an #else clause. +#else // BOOST_PP_IS_ITERATING +#if BOOST_PP_ITERATION_DEPTH() == 1 // defined(BOOST_PP_IS_ITERATING) + +# define N BOOST_PP_ITERATION() + + // as 'get_signature(RT(*)(T0...TN), void* = 0)' is the same + // function as 'get_signature(RT(__cdecl *)(T0...TN), void* = 0)', + // we don't define it twice +# if !defined(BOOST_PYTHON_FN_CC_IS_CDECL) + +template < + class RT BOOST_PP_ENUM_TRAILING_PARAMS_Z(1, N, class T)> +inline BOOST_PYTHON_LIST_INC(N)< + RT BOOST_PP_ENUM_TRAILING_PARAMS_Z(1, N, T)> +get_signature(RT(BOOST_PYTHON_FN_CC *)(BOOST_PP_ENUM_PARAMS_Z(1, N, T)), void* = 0) +{ + return BOOST_PYTHON_LIST_INC(N)< + RT BOOST_PP_ENUM_TRAILING_PARAMS_Z(1, N, T) + >(); +} + +# endif // !defined(BOOST_PYTHON_FN_CC_IS_CDECL) + +# undef N + +# define BOOST_PP_ITERATION_PARAMS_2 \ + (3, (0, 3, <boost/python/signature.hpp>)) +# include BOOST_PP_ITERATE() + +#else + +# define N BOOST_PP_RELATIVE_ITERATION(1) +# define Q BOOST_PYTHON_CV_QUALIFIER(BOOST_PP_ITERATION()) + +template < + class RT, class ClassT BOOST_PP_ENUM_TRAILING_PARAMS_Z(1, N, class T)> +inline BOOST_PYTHON_LIST_INC(BOOST_PP_INC(N))< + RT, ClassT& BOOST_PP_ENUM_TRAILING_PARAMS_Z(1, N, T)> +get_signature(RT(BOOST_PYTHON_FN_CC ClassT::*)(BOOST_PP_ENUM_PARAMS_Z(1, N, T)) Q) +{ + return BOOST_PYTHON_LIST_INC(BOOST_PP_INC(N))< + RT, ClassT& BOOST_PP_ENUM_TRAILING_PARAMS_Z(1, N, T) + >(); +} + +template < + class Target + , class RT + , class ClassT + BOOST_PP_ENUM_TRAILING_PARAMS_Z(1, N, class T) +> +inline BOOST_PYTHON_LIST_INC(BOOST_PP_INC(N))< + RT + , typename most_derived<Target, ClassT>::type& + BOOST_PP_ENUM_TRAILING_PARAMS_Z(1, N, T) +> +get_signature( + RT(BOOST_PYTHON_FN_CC ClassT::*)(BOOST_PP_ENUM_PARAMS_Z(1, N, T)) Q + , Target* +) +{ + return BOOST_PYTHON_LIST_INC(BOOST_PP_INC(N))< + RT + , BOOST_DEDUCED_TYPENAME most_derived<Target, ClassT>::type& + BOOST_PP_ENUM_TRAILING_PARAMS_Z(1, N, T) + >(); +} + +# undef Q +# undef N + +#endif // BOOST_PP_ITERATION_DEPTH() +#endif // !defined(BOOST_PP_IS_ITERATING) diff --git a/boost/python/slice.hpp b/boost/python/slice.hpp new file mode 100644 index 0000000000..19f316a1e7 --- /dev/null +++ b/boost/python/slice.hpp @@ -0,0 +1,276 @@ +#ifndef BOOST_PYTHON_SLICE_JDB20040105_HPP +#define BOOST_PYTHON_SLICE_JDB20040105_HPP + +// Copyright (c) 2004 Jonathan Brandmeyer +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include <boost/python/detail/prefix.hpp> +#include <boost/config.hpp> +#include <boost/python/object.hpp> +#include <boost/python/extract.hpp> +#include <boost/python/converter/pytype_object_mgr_traits.hpp> + +#include <boost/iterator/iterator_traits.hpp> + +#include <iterator> +#include <algorithm> + +namespace boost { namespace python { + +namespace detail +{ + class BOOST_PYTHON_DECL slice_base : public object + { + public: + // Get the Python objects associated with the slice. In principle, these + // may be any arbitrary Python type, but in practice they are usually + // integers. If one or more parameter is ommited in the Python expression + // that created this slice, than that parameter is None here, and compares + // equal to a default-constructed boost::python::object. + // If a user-defined type wishes to support slicing, then support for the + // special meaning associated with negative indices is up to the user. + object start() const; + object stop() const; + object step() const; + + protected: + explicit slice_base(PyObject*, PyObject*, PyObject*); + + BOOST_PYTHON_FORWARD_OBJECT_CONSTRUCTORS(slice_base, object) + }; +} + +class slice : public detail::slice_base +{ + typedef detail::slice_base base; + public: + // Equivalent to slice(::) + slice() : base(0,0,0) {} + + // Each argument must be slice_nil, or implicitly convertable to object. + // They should normally be integers. + template<typename Integer1, typename Integer2> + slice( Integer1 start, Integer2 stop) + : base( object(start).ptr(), object(stop).ptr(), 0 ) + {} + + template<typename Integer1, typename Integer2, typename Integer3> + slice( Integer1 start, Integer2 stop, Integer3 stride) + : base( object(start).ptr(), object(stop).ptr(), object(stride).ptr() ) + {} + + // The following algorithm is intended to automate the process of + // determining a slice range when you want to fully support negative + // indices and non-singular step sizes. Its functionallity is simmilar to + // PySlice_GetIndicesEx() in the Python/C API, but tailored for C++ users. + // This template returns a slice::range struct that, when used in the + // following iterative loop, will traverse a slice of the function's + // arguments. + // while (start != end) { + // do_foo(...); + // std::advance( start, step); + // } + // do_foo(...); // repeat exactly once more. + + // Arguments: a [begin, end) pair of STL-conforming random-access iterators. + + // Return: slice::range, where start and stop define a _closed_ interval + // that covers at most [begin, end-1] of the provided arguments, and a step + // that is non-zero. + + // Throws: error_already_set() if any of the indices are neither None nor + // integers, or the slice has a step value of zero. + // std::invalid_argument if the resulting range would be empty. Normally, + // you should catch this exception and return an empty sequence of the + // appropriate type. + + // Performance: constant time for random-access iterators. + + // Rationale: + // closed-interval: If an open interval were used, then for a non-singular + // value for step, the required state for the end iterator could be + // beyond the one-past-the-end postion of the specified range. While + // probably harmless, the behavior of STL-conforming iterators is + // undefined in this case. + // exceptions on zero-length range: It is impossible to define a closed + // interval over an empty range, so some other form of error checking + // would have to be used by the user to prevent undefined behavior. In + // the case where the user fails to catch the exception, it will simply + // be translated to Python by the default exception handling mechanisms. + + template<typename RandomAccessIterator> + struct range + { + RandomAccessIterator start; + RandomAccessIterator stop; + typename iterator_difference<RandomAccessIterator>::type step; + }; + + template<typename RandomAccessIterator> + slice::range<RandomAccessIterator> + get_indices( const RandomAccessIterator& begin, + const RandomAccessIterator& end) const + { + // This is based loosely on PySlice_GetIndicesEx(), but it has been + // carefully crafted to ensure that these iterators never fall out of + // the range of the container. + slice::range<RandomAccessIterator> ret; + + typedef typename iterator_difference<RandomAccessIterator>::type difference_type; + difference_type max_dist = boost::detail::distance(begin, end); + + object slice_start = this->start(); + object slice_stop = this->stop(); + object slice_step = this->step(); + + // Extract the step. + if (slice_step == object()) { + ret.step = 1; + } + else { + ret.step = extract<long>( slice_step); + if (ret.step == 0) { + PyErr_SetString( PyExc_IndexError, "step size cannot be zero."); + throw_error_already_set(); + } + } + + // Setup the start iterator. + if (slice_start == object()) { + if (ret.step < 0) { + ret.start = end; + --ret.start; + } + else + ret.start = begin; + } + else { + difference_type i = extract<long>( slice_start); + if (i >= max_dist && ret.step > 0) + throw std::invalid_argument( "Zero-length slice"); + if (i >= 0) { + ret.start = begin; + BOOST_USING_STD_MIN(); + std::advance( ret.start, min BOOST_PREVENT_MACRO_SUBSTITUTION(i, max_dist-1)); + } + else { + if (i < -max_dist && ret.step < 0) + throw std::invalid_argument( "Zero-length slice"); + ret.start = end; + // Advance start (towards begin) not farther than begin. + std::advance( ret.start, (-i < max_dist) ? i : -max_dist ); + } + } + + // Set up the stop iterator. This one is a little trickier since slices + // define a [) range, and we are returning a [] range. + if (slice_stop == object()) { + if (ret.step < 0) { + ret.stop = begin; + } + else { + ret.stop = end; + std::advance( ret.stop, -1); + } + } + else { + difference_type i = extract<long>(slice_stop); + // First, branch on which direction we are going with this. + if (ret.step < 0) { + if (i+1 >= max_dist || i == -1) + throw std::invalid_argument( "Zero-length slice"); + + if (i >= 0) { + ret.stop = begin; + std::advance( ret.stop, i+1); + } + else { // i is negative, but more negative than -1. + ret.stop = end; + std::advance( ret.stop, (-i < max_dist) ? i : -max_dist); + } + } + else { // stepping forward + if (i == 0 || -i >= max_dist) + throw std::invalid_argument( "Zero-length slice"); + + if (i > 0) { + ret.stop = begin; + std::advance( ret.stop, (std::min)( i-1, max_dist-1)); + } + else { // i is negative, but not more negative than -max_dist + ret.stop = end; + std::advance( ret.stop, i-1); + } + } + } + + // Now the fun part, handling the possibilites surrounding step. + // At this point, step has been initialized, ret.stop, and ret.step + // represent the widest possible range that could be traveled + // (inclusive), and final_dist is the maximum distance covered by the + // slice. + typename iterator_difference<RandomAccessIterator>::type final_dist = + boost::detail::distance( ret.start, ret.stop); + + // First case, if both ret.start and ret.stop are equal, then step + // is irrelevant and we can return here. + if (final_dist == 0) + return ret; + + // Second, if there is a sign mismatch, than the resulting range and + // step size conflict: std::advance( ret.start, ret.step) goes away from + // ret.stop. + if ((final_dist > 0) != (ret.step > 0)) + throw std::invalid_argument( "Zero-length slice."); + + // Finally, if the last step puts us past the end, we move ret.stop + // towards ret.start in the amount of the remainder. + // I don't remember all of the oolies surrounding negative modulii, + // so I am handling each of these cases separately. + if (final_dist < 0) { + difference_type remainder = -final_dist % -ret.step; + std::advance( ret.stop, remainder); + } + else { + difference_type remainder = final_dist % ret.step; + std::advance( ret.stop, -remainder); + } + + return ret; + } + + // Incorrect spelling. DO NOT USE. Only here for backward compatibility. + // Corrected 2011-06-14. + template<typename RandomAccessIterator> + slice::range<RandomAccessIterator> + get_indicies( const RandomAccessIterator& begin, + const RandomAccessIterator& end) const + { + return get_indices(begin, end); + } + + public: + // This declaration, in conjunction with the specialization of + // object_manager_traits<> below, allows C++ functions accepting slice + // arguments to be called from from Python. These constructors should never + // be used in client code. + BOOST_PYTHON_FORWARD_OBJECT_CONSTRUCTORS(slice, detail::slice_base) +}; + + +namespace converter { + +template<> +struct object_manager_traits<slice> + : pytype_object_manager_traits<&PySlice_Type, slice> +{ +}; + +} // !namesapce converter + +} } // !namespace ::boost::python + + +#endif // !defined BOOST_PYTHON_SLICE_JDB20040105_HPP diff --git a/boost/python/slice_nil.hpp b/boost/python/slice_nil.hpp new file mode 100644 index 0000000000..e911f06801 --- /dev/null +++ b/boost/python/slice_nil.hpp @@ -0,0 +1,44 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef SLICE_NIL_DWA2002620_HPP +# define SLICE_NIL_DWA2002620_HPP + +# include <boost/python/detail/prefix.hpp> +# include <boost/python/object_core.hpp> + +namespace boost { namespace python { namespace api { + +class slice_nil : public object +{ + public: + slice_nil() : object() {} +}; + +# ifndef _ // Watch out for GNU gettext users, who #define _(x) +static const slice_nil _ = slice_nil(); +# endif + +template <class T> +struct slice_bound +{ + typedef object type; +}; + +template <> +struct slice_bound<slice_nil> +{ + typedef slice_nil type; +}; + +} + +using api::slice_nil; +# ifndef _ // Watch out for GNU gettext users, who #define _(x) +using api::_; +# endif + +}} // namespace boost::python + +#endif // SLICE_NIL_DWA2002620_HPP diff --git a/boost/python/ssize_t.hpp b/boost/python/ssize_t.hpp new file mode 100644 index 0000000000..e8a2d92f63 --- /dev/null +++ b/boost/python/ssize_t.hpp @@ -0,0 +1,29 @@ +// Copyright Ralf W. Grosse-Kunstleve & David Abrahams 2006. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_PYTHON_SSIZE_T_RWGK20060924_HPP +# define BOOST_PYTHON_SSIZE_T_RWGK20060924_HPP + +# include <boost/python/detail/prefix.hpp> + +namespace boost { namespace python { + +#if PY_VERSION_HEX >= 0x02050000 + +typedef Py_ssize_t ssize_t; +ssize_t const ssize_t_max = PY_SSIZE_T_MAX; +ssize_t const ssize_t_min = PY_SSIZE_T_MIN; + +#else + +typedef int ssize_t; +ssize_t const ssize_t_max = INT_MAX; +ssize_t const ssize_t_min = INT_MIN; + +#endif + +}} // namespace boost::python + +#endif // BOOST_PYTHON_SSIZE_T_RWGK20060924_HPP diff --git a/boost/python/stl_iterator.hpp b/boost/python/stl_iterator.hpp new file mode 100644 index 0000000000..838954879a --- /dev/null +++ b/boost/python/stl_iterator.hpp @@ -0,0 +1,61 @@ +// Copyright Eric Niebler 2005. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef STL_ITERATOR_EAN20051028_HPP +# define STL_ITERATOR_EAN20051028_HPP + +# include <boost/python/detail/prefix.hpp> + +# include <boost/python/object/stl_iterator_core.hpp> + +# include <boost/iterator/iterator_facade.hpp> + +namespace boost { namespace python +{ + +// An STL input iterator over a python sequence +template<typename ValueT> +struct stl_input_iterator + : boost::iterator_facade< + stl_input_iterator<ValueT> + , ValueT + , std::input_iterator_tag + , ValueT + > +{ + stl_input_iterator() + : impl_() + { + } + + // ob is the python sequence + stl_input_iterator(boost::python::object const &ob) + : impl_(ob) + { + } + +private: + friend class boost::iterator_core_access; + + void increment() + { + this->impl_.increment(); + } + + ValueT dereference() const + { + return extract<ValueT>(this->impl_.current().get())(); + } + + bool equal(stl_input_iterator<ValueT> const &that) const + { + return this->impl_.equal(that.impl_); + } + + objects::stl_input_iterator_impl impl_; +}; + +}} // namespace boost::python + +#endif // STL_ITERATOR_EAN20051028_HPP diff --git a/boost/python/str.hpp b/boost/python/str.hpp new file mode 100644 index 0000000000..426a3a255c --- /dev/null +++ b/boost/python/str.hpp @@ -0,0 +1,422 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef STR_20020703_HPP +#define STR_20020703_HPP + +# include <boost/python/detail/prefix.hpp> + +#include <boost/python/object.hpp> +#include <boost/python/list.hpp> +#include <boost/python/converter/pytype_object_mgr_traits.hpp> + +// disable defines in <cctype> provided by some system libraries +#undef isspace +#undef islower +#undef isalpha +#undef isdigit +#undef isalnum +#undef isupper + +namespace boost { namespace python { + +class str; + +namespace detail +{ + struct BOOST_PYTHON_DECL str_base : object + { + str capitalize() const; + + str center(object_cref width) const; + + long count(object_cref sub) const; + + long count(object_cref sub, object_cref start) const; + + long count(object_cref sub, object_cref start, object_cref end) const; + +#if PY_VERSION_HEX < 0x03000000 + object decode() const; + object decode(object_cref encoding) const; + + object decode(object_cref encoding, object_cref errors) const; +#endif + + object encode() const; + object encode(object_cref encoding) const; + object encode(object_cref encoding, object_cref errors) const; + + bool endswith(object_cref suffix) const; + + bool endswith(object_cref suffix, object_cref start) const; + bool endswith(object_cref suffix, object_cref start, object_cref end) const; + + str expandtabs() const; + str expandtabs(object_cref tabsize) const; + + long find(object_cref sub) const; + long find(object_cref sub, object_cref start) const; + + long find(object_cref sub, object_cref start, object_cref end) const; + + long index(object_cref sub) const; + + long index(object_cref sub, object_cref start) const; + long index(object_cref sub, object_cref start, object_cref end) const; + + bool isalnum() const; + bool isalpha() const; + bool isdigit() const; + bool islower() const; + bool isspace() const; + bool istitle() const; + bool isupper() const; + + str join(object_cref sequence) const; + + str ljust(object_cref width) const; + str lower() const; + str lstrip() const; + + str replace(object_cref old, object_cref new_) const; + str replace(object_cref old, object_cref new_, object_cref maxsplit) const; + long rfind(object_cref sub) const; + + long rfind(object_cref sub, object_cref start) const; + + long rfind(object_cref sub, object_cref start, object_cref end) const; + long rindex(object_cref sub) const; + long rindex(object_cref sub, object_cref start) const; + + + long rindex(object_cref sub, object_cref start, object_cref end) const; + + str rjust(object_cref width) const; + + str rstrip() const; + + list split() const; + list split(object_cref sep) const; + + list split(object_cref sep, object_cref maxsplit) const; + + + list splitlines() const; + list splitlines(object_cref keepends) const; + + bool startswith(object_cref prefix) const; + + + bool startswith(object_cref prefix, object_cref start) const; + bool startswith(object_cref prefix, object_cref start, object_cref end) const; + + str strip() const; + str swapcase() const; + str title() const; + + str translate(object_cref table) const; + + str translate(object_cref table, object_cref deletechars) const; + + + str upper() const; + + protected: + str_base(); // new str + + str_base(const char* s); // new str + + str_base(char const* start, char const* finish); + + str_base(char const* start, std::size_t length); + + explicit str_base(object_cref other); + + BOOST_PYTHON_FORWARD_OBJECT_CONSTRUCTORS(str_base, object) + private: + static new_reference call(object const&); + }; +} + + +class str : public detail::str_base +{ + typedef detail::str_base base; + public: + str() {} // new str + + str(const char* s) : base(s) {} // new str + + str(char const* start, char const* finish) // new str + : base(start, finish) + {} + + str(char const* start, std::size_t length) // new str + : base(start, length) + {} + + template <class T> + explicit str(T const& other) + : base(object(other)) + { + } + + template <class T> + str center(T const& width) const + { + return base::center(object(width)); + } + + template<class T> + long count(T const& sub) const + { + return base::count(object(sub)); + } + + template<class T1, class T2> + long count(T1 const& sub,T2 const& start) const + { + return base::count(object(sub), object(start)); + } + + template<class T1, class T2, class T3> + long count(T1 const& sub,T2 const& start, T3 const& end) const + { + return base::count(object(sub), object(start)); + } + +#if PY_VERSION_HEX < 0x03000000 + object decode() const { return base::decode(); } + + template<class T> + object decode(T const& encoding) const + { + return base::decode(object(encoding)); + } + + template<class T1, class T2> + object decode(T1 const& encoding, T2 const& errors) const + { + return base::decode(object(encoding),object(errors)); + } +#endif + + object encode() const { return base::encode(); } + + template <class T> + object encode(T const& encoding) const + { + return base::encode(object(encoding)); + } + + template <class T1, class T2> + object encode(T1 const& encoding, T2 const& errors) const + { + return base::encode(object(encoding),object(errors)); + } + + template <class T> + bool endswith(T const& suffix) const + { + return base::endswith(object(suffix)); + } + + template <class T1, class T2> + bool endswith(T1 const& suffix, T2 const& start) const + { + return base::endswith(object(suffix), object(start)); + } + + template <class T1, class T2, class T3> + bool endswith(T1 const& suffix, T2 const& start, T3 const& end) const + { + return base::endswith(object(suffix), object(start), object(end)); + } + + str expandtabs() const { return base::expandtabs(); } + + template <class T> + str expandtabs(T const& tabsize) const + { + return base::expandtabs(object(tabsize)); + } + + template <class T> + long find(T const& sub) const + { + return base::find(object(sub)); + } + + template <class T1, class T2> + long find(T1 const& sub, T2 const& start) const + { + return base::find(object(sub), object(start)); + } + + template <class T1, class T2, class T3> + long find(T1 const& sub, T2 const& start, T3 const& end) const + { + return base::find(object(sub), object(start), object(end)); + } + + template <class T> + long index(T const& sub) const + { + return base::index(object(sub)); + } + + template <class T1, class T2> + long index(T1 const& sub, T2 const& start) const + { + return base::index(object(sub), object(start)); + } + + template <class T1, class T2, class T3> + long index(T1 const& sub, T2 const& start, T3 const& end) const + { + return base::index(object(sub), object(start), object(end)); + } + + template <class T> + str join(T const& sequence) const + { + return base::join(object(sequence)); + } + + template <class T> + str ljust(T const& width) const + { + return base::ljust(object(width)); + } + + template <class T1, class T2> + str replace(T1 const& old, T2 const& new_) const + { + return base::replace(object(old),object(new_)); + } + + template <class T1, class T2, class T3> + str replace(T1 const& old, T2 const& new_, T3 const& maxsplit) const + { + return base::replace(object(old),object(new_), object(maxsplit)); + } + + template <class T> + long rfind(T const& sub) const + { + return base::rfind(object(sub)); + } + + template <class T1, class T2> + long rfind(T1 const& sub, T2 const& start) const + { + return base::rfind(object(sub), object(start)); + } + + template <class T1, class T2, class T3> + long rfind(T1 const& sub, T2 const& start, T3 const& end) const + { + return base::rfind(object(sub), object(start), object(end)); + } + + template <class T> + long rindex(T const& sub) const + { + return base::rindex(object(sub)); + } + + template <class T1, class T2> + long rindex(T1 const& sub, T2 const& start) const + { + return base::rindex(object(sub), object(start)); + } + + template <class T1, class T2, class T3> + long rindex(T1 const& sub, T2 const& start, T3 const& end) const + { + return base::rindex(object(sub), object(start), object(end)); + } + + template <class T> + str rjust(T const& width) const + { + return base::rjust(object(width)); + } + + list split() const { return base::split(); } + + template <class T> + list split(T const& sep) const + { + return base::split(object(sep)); + } + + template <class T1, class T2> + list split(T1 const& sep, T2 const& maxsplit) const + { + return base::split(object(sep), object(maxsplit)); + } + + list splitlines() const { return base::splitlines(); } + + template <class T> + list splitlines(T const& keepends) const + { + return base::splitlines(object(keepends)); + } + + template <class T> + bool startswith(T const& prefix) const + { + return base::startswith(object(prefix)); + } + + template <class T1, class T2> + bool startswith(T1 const& prefix, T2 const& start) const + { + return base::startswith(object(prefix), object(start)); + } + + template <class T1, class T2, class T3> + bool startswith(T1 const& prefix, T2 const& start, T3 const& end) const + { + return base::startswith(object(prefix), object(start), object(end)); + } + + template <class T> + str translate(T const& table) const + { + return base::translate(object(table)); + } + + template <class T1, class T2> + str translate(T1 const& table, T2 const& deletechars) const + { + return base::translate(object(table), object(deletechars)); + } + + public: // implementation detail -- for internal use only + BOOST_PYTHON_FORWARD_OBJECT_CONSTRUCTORS(str, base) +}; + +// +// Converter Specializations +// +namespace converter +{ + template <> + struct object_manager_traits<str> +#if PY_VERSION_HEX >= 0x03000000 + : pytype_object_manager_traits<&PyUnicode_Type,str> +#else + : pytype_object_manager_traits<&PyString_Type,str> +#endif + { + }; +} + +}} // namespace boost::python + +#endif // STR_20020703_HPP diff --git a/boost/python/suite/indexing/container_utils.hpp b/boost/python/suite/indexing/container_utils.hpp new file mode 100644 index 0000000000..72710bb8b0 --- /dev/null +++ b/boost/python/suite/indexing/container_utils.hpp @@ -0,0 +1,57 @@ + +// (C) Copyright Joel de Guzman 2003. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef PY_CONTAINER_UTILS_JDG20038_HPP +# define PY_CONTAINER_UTILS_JDG20038_HPP + +# include <utility> +# include <boost/foreach.hpp> +# include <boost/python/object.hpp> +# include <boost/python/handle.hpp> +# include <boost/python/extract.hpp> +# include <boost/python/stl_iterator.hpp> + +namespace boost { namespace python { namespace container_utils { + + template <typename Container> + void + extend_container(Container& container, object l) + { + typedef typename Container::value_type data_type; + + // l must be iterable + BOOST_FOREACH(object elem, + std::make_pair( + boost::python::stl_input_iterator<object>(l), + boost::python::stl_input_iterator<object>() + )) + { + extract<data_type const&> x(elem); + // try if elem is an exact data_type type + if (x.check()) + { + container.push_back(x()); + } + else + { + // try to convert elem to data_type type + extract<data_type> x(elem); + if (x.check()) + { + container.push_back(x()); + } + else + { + PyErr_SetString(PyExc_TypeError, "Incompatible Data Type"); + throw_error_already_set(); + } + } + } + } + +}}} // namespace boost::python::container_utils + +#endif diff --git a/boost/python/suite/indexing/detail/indexing_suite_detail.hpp b/boost/python/suite/indexing/detail/indexing_suite_detail.hpp new file mode 100644 index 0000000000..70df8a7273 --- /dev/null +++ b/boost/python/suite/indexing/detail/indexing_suite_detail.hpp @@ -0,0 +1,759 @@ +// (C) Copyright Joel de Guzman 2003. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef INDEXING_SUITE_DETAIL_JDG20036_HPP +# define INDEXING_SUITE_DETAIL_JDG20036_HPP + +# include <boost/python/extract.hpp> +# include <boost/scoped_ptr.hpp> +# include <boost/get_pointer.hpp> +# include <boost/detail/binary_search.hpp> +# include <boost/numeric/conversion/cast.hpp> +# include <boost/type_traits/is_pointer.hpp> +# include <vector> +# include <map> +#include <iostream> + +namespace boost { namespace python { namespace detail { + +#if defined(NDEBUG) +#define BOOST_PYTHON_INDEXING_CHECK_INVARIANT +#else +#define BOOST_PYTHON_INDEXING_CHECK_INVARIANT check_invariant() +#endif + + template <class Proxy> + struct compare_proxy_index + { + // This functor compares a proxy and an index. + // This is used by proxy_group::first_proxy to + // get first proxy with index i. + + template <class Index> + bool operator()(PyObject* prox, Index i) const + { + typedef typename Proxy::policies_type policies_type; + Proxy& proxy = extract<Proxy&>(prox)(); + return policies_type:: + compare_index(proxy.get_container(), proxy.get_index(), i); + } + }; + + // The proxy_group class holds a vector of container element + // proxies. First, what is a container element proxy? A container + // element proxy acts like a smart pointer holding a reference to + // a container and an index (see container_element, for details). + // + // The proxies are held in a vector always sorted by its index. + // Various functions manage the addition, removal and searching + // of proxies from the vector. + // + template <class Proxy> + class proxy_group + { + public: + + typedef typename std::vector<PyObject*>::const_iterator const_iterator; + typedef typename std::vector<PyObject*>::iterator iterator; + typedef typename Proxy::index_type index_type; + typedef typename Proxy::policies_type policies_type; + + iterator + first_proxy(index_type i) + { + // Return the first proxy with index <= i + return boost::detail::lower_bound( + proxies.begin(), proxies.end(), + i, compare_proxy_index<Proxy>()); + } + + void + remove(Proxy& proxy) + { + // Remove a proxy + for (iterator iter = first_proxy(proxy.get_index()); + iter != proxies.end(); ++iter) + { + if (&extract<Proxy&>(*iter)() == &proxy) + { + proxies.erase(iter); + break; + } + } + BOOST_PYTHON_INDEXING_CHECK_INVARIANT; + } + + void + add(PyObject* prox) + { + BOOST_PYTHON_INDEXING_CHECK_INVARIANT; + // Add a proxy + proxies.insert( + first_proxy(extract<Proxy&>(prox)().get_index()), prox); + BOOST_PYTHON_INDEXING_CHECK_INVARIANT; + } + + void + erase(index_type i, mpl::false_) + { + BOOST_PYTHON_INDEXING_CHECK_INVARIANT; + // Erase the proxy with index i + replace(i, i+1, 0); + BOOST_PYTHON_INDEXING_CHECK_INVARIANT; + } + + void + erase(index_type i, mpl::true_) + { + BOOST_PYTHON_INDEXING_CHECK_INVARIANT; + // Erase the proxy with index i + + iterator iter = first_proxy(i); + extract<Proxy&> p(*iter); + + if (iter != proxies.end() && p().get_index() == i) + { + extract<Proxy&> p(*iter); + p().detach(); + proxies.erase(iter); + } + BOOST_PYTHON_INDEXING_CHECK_INVARIANT; + } + + void + erase(index_type from, index_type to) + { + // note: this cannot be called when container is not sliceable + + BOOST_PYTHON_INDEXING_CHECK_INVARIANT; + // Erase all proxies with indexes from..to + replace(from, to, 0); + BOOST_PYTHON_INDEXING_CHECK_INVARIANT; + } + + void + replace( + index_type from, + index_type to, + typename std::vector<PyObject*>::size_type len) + { + // note: this cannot be called when container is not sliceable + + BOOST_PYTHON_INDEXING_CHECK_INVARIANT; + // Erase all proxies with indexes from..to. + // Adjust the displaced indexes such that the + // final effect is that we have inserted *len* + // number of proxies in the vacated region. This + // procedure involves adjusting the indexes of + // the proxies. + + iterator left = first_proxy(from); + iterator right = proxies.end(); // we'll adjust this later + + for (iterator iter = left; iter != right; ++iter) + { + if (extract<Proxy&>(*iter)().get_index() > to) + { + right = iter; // adjust right + break; + } + extract<Proxy&> p(*iter); + p().detach(); + } + + typename std::vector<PyObject*>::size_type + offset = left-proxies.begin(); + proxies.erase(left, right); + right = proxies.begin()+offset; + + while (right != proxies.end()) + { + typedef typename Proxy::container_type::difference_type difference_type; + extract<Proxy&> p(*right); + p().set_index( + extract<Proxy&>(*right)().get_index() + - (difference_type(to) - from - len) + ); + + ++right; + } + BOOST_PYTHON_INDEXING_CHECK_INVARIANT; + } + + PyObject* + find(index_type i) + { + BOOST_PYTHON_INDEXING_CHECK_INVARIANT; + // Find the proxy with *exact* index i. + // Return 0 (null) if no proxy with the + // given index is found. + iterator iter = first_proxy(i); + if (iter != proxies.end() + && extract<Proxy&>(*iter)().get_index() == i) + { + BOOST_PYTHON_INDEXING_CHECK_INVARIANT; + return *iter; + } + BOOST_PYTHON_INDEXING_CHECK_INVARIANT; + return 0; + } + + typename std::vector<PyObject*>::size_type + size() const + { + BOOST_PYTHON_INDEXING_CHECK_INVARIANT; + // How many proxies are there so far? + return proxies.size(); + } + + private: + +#if !defined(NDEBUG) + void + check_invariant() const + { + for (const_iterator i = proxies.begin(); i != proxies.end(); ++i) + { + if ((*i)->ob_refcnt <= 0) + { + PyErr_SetString(PyExc_RuntimeError, + "Invariant: Proxy vector in an inconsistent state"); + throw_error_already_set(); + } + + if (i+1 != proxies.end()) + { + if (extract<Proxy&>(*(i+1))().get_index() == + extract<Proxy&>(*(i))().get_index()) + { + PyErr_SetString(PyExc_RuntimeError, + "Invariant: Proxy vector in an inconsistent state (duplicate proxy)"); + throw_error_already_set(); + } + } + } + } +#endif + + std::vector<PyObject*> proxies; + }; + + // proxy_links holds a map of Container pointers (keys) + // with proxy_group(s) (data). Various functions manage + // the addition, removal and searching of proxies from + // the map. + // + template <class Proxy, class Container> + class proxy_links + { + public: + + typedef std::map<Container*, proxy_group<Proxy> > links_t; + typedef typename Proxy::index_type index_type; + + void + remove(Proxy& proxy) + { + // Remove a proxy. + typename links_t::iterator r = links.find(&proxy.get_container()); + if (r != links.end()) + { + r->second.remove(proxy); + if (r->second.size() == 0) + links.erase(r); + } + } + + void + add(PyObject* prox, Container& container) + { + // Add a proxy + links[&container].add(prox); + } + + template <class NoSlice> + void erase(Container& container, index_type i, NoSlice no_slice) + { + // Erase the proxy with index i + typename links_t::iterator r = links.find(&container); + if (r != links.end()) + { + r->second.erase(i, no_slice); + if (r->second.size() == 0) + links.erase(r); + } + } + + void + erase(Container& container, index_type from, index_type to) + { + // Erase all proxies with indexes from..to + typename links_t::iterator r = links.find(&container); + if (r != links.end()) + { + r->second.erase(from, to); + if (r->second.size() == 0) + links.erase(r); + } + } + + void + replace( + Container& container, + index_type from, index_type to, index_type len) + { + // Erase all proxies with indexes from..to. + // Adjust the displaced indexes such that the + // final effect is that we have inserted *len* + // number of proxies in the vacated region. This + // procedure involves adjusting the indexes of + // the proxies. + + typename links_t::iterator r = links.find(&container); + if (r != links.end()) + { + r->second.replace(from, to, len); + if (r->second.size() == 0) + links.erase(r); + } + } + + PyObject* + find(Container& container, index_type i) + { + // Find the proxy with *exact* index i. + // Return 0 (null) if no proxy with the given + // index is found. + typename links_t::iterator r = links.find(&container); + if (r != links.end()) + return r->second.find(i); + return 0; + } + + private: + + links_t links; + }; + + // container_element is our container proxy class. + // This class acts like a smart pointer to a container + // element. The class holds an index and a reference to + // a container. Dereferencing the smart pointer will + // retrieve the nth (index) element from the container. + // + // A container_element can also be detached from the + // container. In such a detached state, the container_element + // holds a copy of the nth (index) element, which it + // returns when dereferenced. + // + template <class Container, class Index, class Policies> + class container_element + { + public: + + typedef Index index_type; + typedef Container container_type; + typedef typename Policies::data_type element_type; + typedef Policies policies_type; + typedef container_element<Container, Index, Policies> self_t; + typedef proxy_group<self_t> links_type; + + container_element(object container, Index index) + : ptr() + , container(container) + , index(index) + { + } + + container_element(container_element const& ce) + : ptr(ce.ptr.get() == 0 ? 0 : new element_type(*ce.ptr.get())) + , container(ce.container) + , index(ce.index) + { + } + + ~container_element() + { + if (!is_detached()) + get_links().remove(*this); + } + + element_type& operator*() const + { + if (is_detached()) + return *get_pointer(ptr); + return Policies::get_item(get_container(), index); + } + + element_type* get() const + { + if (is_detached()) + return get_pointer(ptr); + return &Policies::get_item(get_container(), index); + } + + void + detach() + { + if (!is_detached()) + { + ptr.reset( + new element_type( + Policies::get_item(get_container(), index))); + container = object(); // free container. reset it to None + } + } + + bool + is_detached() const + { + return get_pointer(ptr) != 0; + } + + Container& + get_container() const + { + return extract<Container&>(container)(); + } + + Index + get_index() const + { + return index; + } + + void + set_index(Index i) + { + index = i; + } + + static proxy_links<self_t, Container>& + get_links() + { + // All container_element(s) maintain links to + // its container in a global map (see proxy_links). + // This global "links" map is a singleton. + + static proxy_links<self_t, Container> links; + return links; // singleton + } + + private: + + container_element& operator=(container_element const& ce); + + scoped_ptr<element_type> ptr; + object container; + Index index; + }; + + template < + class Container + , class DerivedPolicies + , class ContainerElement + , class Index + > + struct no_proxy_helper + { + static void + register_container_element() + { + } + + template <class DataType> + static object + base_get_item_helper(DataType const& p, mpl::true_) + { + return object(ptr(p)); + } + + template <class DataType> + static object + base_get_item_helper(DataType const& x, mpl::false_) + { + return object(x); + } + + static object + base_get_item_(back_reference<Container&> const& container, PyObject* i) + { + return base_get_item_helper( + DerivedPolicies::get_item( + container.get(), DerivedPolicies:: + convert_index(container.get(), i)) + , is_pointer<BOOST_DEDUCED_TYPENAME Container::value_type>() + ); + } + + static void + base_replace_indexes( + Container& /*container*/, Index /*from*/, + Index /*to*/, Index /*n*/) + { + } + + template <class NoSlice> + static void + base_erase_index( + Container& /*container*/, Index /*i*/, NoSlice /*no_slice*/) + { + } + + static void + base_erase_indexes(Container& /*container*/, Index /*from*/, Index /*to*/) + { + } + }; + + template < + class Container + , class DerivedPolicies + , class ContainerElement + , class Index + > + struct proxy_helper + { + static void + register_container_element() + { + register_ptr_to_python<ContainerElement>(); + } + + static object + base_get_item_(back_reference<Container&> const& container, PyObject* i) + { + // Proxy + Index idx = DerivedPolicies::convert_index(container.get(), i); + + if (PyObject* shared = + ContainerElement::get_links().find(container.get(), idx)) + { + handle<> h(python::borrowed(shared)); + return object(h); + } + else + { + object prox(ContainerElement(container.source(), idx)); + ContainerElement:: + get_links().add(prox.ptr(), container.get()); + return prox; + } + } + + static void + base_replace_indexes( + Container& container, Index from, + Index to, Index n) + { + ContainerElement::get_links().replace(container, from, to, n); + } + + template <class NoSlice> + static void + base_erase_index( + Container& container, Index i, NoSlice no_slice) + { + ContainerElement::get_links().erase(container, i, no_slice); + } + + static void + base_erase_indexes( + Container& container, Index from, Index to) + { + ContainerElement::get_links().erase(container, from, to); + } + }; + + template < + class Container + , class DerivedPolicies + , class ProxyHandler + , class Data + , class Index + > + struct slice_helper + { + static object + base_get_slice(Container& container, PySliceObject* slice) + { + Index from, to; + base_get_slice_data(container, slice, from, to); + return DerivedPolicies::get_slice(container, from, to); + } + + static void + base_get_slice_data( + Container& container, PySliceObject* slice, Index& from_, Index& to_) + { + if (Py_None != slice->step) { + PyErr_SetString( PyExc_IndexError, "slice step size not supported."); + throw_error_already_set(); + } + + Index min_index = DerivedPolicies::get_min_index(container); + Index max_index = DerivedPolicies::get_max_index(container); + + if (Py_None == slice->start) { + from_ = min_index; + } + else { + long from = extract<long>( slice->start); + if (from < 0) // Negative slice index + from += max_index; + if (from < 0) // Clip lower bounds to zero + from = 0; + from_ = boost::numeric_cast<Index>(from); + if (from_ > max_index) // Clip upper bounds to max_index. + from_ = max_index; + } + + if (Py_None == slice->stop) { + to_ = max_index; + } + else { + long to = extract<long>( slice->stop); + if (to < 0) + to += max_index; + if (to < 0) + to = 0; + to_ = boost::numeric_cast<Index>(to); + if (to_ > max_index) + to_ = max_index; + } + } + + static void + base_set_slice(Container& container, PySliceObject* slice, PyObject* v) + { + Index from, to; + base_get_slice_data(container, slice, from, to); + + extract<Data&> elem(v); + // try if elem is an exact Data + if (elem.check()) + { + ProxyHandler::base_replace_indexes(container, from, to, 1); + DerivedPolicies::set_slice(container, from, to, elem()); + } + else + { + // try to convert elem to Data + extract<Data> elem(v); + if (elem.check()) + { + ProxyHandler::base_replace_indexes(container, from, to, 1); + DerivedPolicies::set_slice(container, from, to, elem()); + } + else + { + // Otherwise, it must be a list or some container + handle<> l_(python::borrowed(v)); + object l(l_); + + std::vector<Data> temp; + for (int i = 0; i < l.attr("__len__")(); i++) + { + object elem(l[i]); + extract<Data const&> x(elem); + // try if elem is an exact Data type + if (x.check()) + { + temp.push_back(x()); + } + else + { + // try to convert elem to Data type + extract<Data> x(elem); + if (x.check()) + { + temp.push_back(x()); + } + else + { + PyErr_SetString(PyExc_TypeError, + "Invalid sequence element"); + throw_error_already_set(); + } + } + } + + ProxyHandler::base_replace_indexes(container, from, to, + temp.end()-temp.begin()); + DerivedPolicies::set_slice(container, from, to, + temp.begin(), temp.end()); + } + } + } + + static void + base_delete_slice(Container& container, PySliceObject* slice) + { + Index from, to; + base_get_slice_data(container, slice, from, to); + ProxyHandler::base_erase_indexes(container, from, to); + DerivedPolicies::delete_slice(container, from, to); + } + }; + + template < + class Container + , class DerivedPolicies + , class ProxyHandler + , class Data + , class Index + > + struct no_slice_helper + { + static void + slicing_not_suported() + { + PyErr_SetString(PyExc_RuntimeError, "Slicing not supported"); + throw_error_already_set(); + } + + static object + base_get_slice(Container& /*container*/, PySliceObject* /*slice*/) + { + slicing_not_suported(); + return object(); + } + + static void + base_set_slice(Container& /*container*/, PySliceObject* /*slice*/, PyObject* /*v*/) + { + slicing_not_suported(); + } + + static void + base_delete_slice(Container& /*container*/, PySliceObject* /*slice*/) + { + slicing_not_suported(); + } + }; + +#ifdef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP +}} // namespace python::detail +#endif + + template <class Container, class Index, class Policies> + inline typename Policies::data_type* + get_pointer( + python::detail::container_element<Container, Index, Policies> const& p) + { + // Get the pointer of a container_element smart pointer + return p.get(); + } + +#ifndef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP + // Don't hide these other get_pointer overloads + using boost::python::get_pointer; + using boost::get_pointer; +}} // namespace python::detail +#endif + +} // namespace boost + +#endif // INDEXING_SUITE_DETAIL_JDG20036_HPP diff --git a/boost/python/suite/indexing/indexing_suite.hpp b/boost/python/suite/indexing/indexing_suite.hpp new file mode 100644 index 0000000000..b636b2111c --- /dev/null +++ b/boost/python/suite/indexing/indexing_suite.hpp @@ -0,0 +1,299 @@ +// (C) Copyright Joel de Guzman 2003. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef INDEXING_SUITE_JDG20036_HPP +# define INDEXING_SUITE_JDG20036_HPP + +# include <boost/python/class.hpp> +# include <boost/python/def_visitor.hpp> +# include <boost/python/register_ptr_to_python.hpp> +# include <boost/python/suite/indexing/detail/indexing_suite_detail.hpp> +# include <boost/python/return_internal_reference.hpp> +# include <boost/python/iterator.hpp> +# include <boost/mpl/or.hpp> +# include <boost/mpl/not.hpp> +# include <boost/type_traits/is_same.hpp> + +namespace boost { namespace python { + + // indexing_suite class. This class is the facade class for + // the management of C++ containers intended to be integrated + // to Python. The objective is make a C++ container look and + // feel and behave exactly as we'd expect a Python container. + // By default indexed elements are returned by proxy. This can be + // disabled by supplying *true* in the NoProxy template parameter. + // + // Derived classes provide the hooks needed by the indexing_suite + // to do its job: + // + // static data_type& + // get_item(Container& container, index_type i); + // + // static object + // get_slice(Container& container, index_type from, index_type to); + // + // static void + // set_item(Container& container, index_type i, data_type const& v); + // + // static void + // set_slice( + // Container& container, index_type from, + // index_type to, data_type const& v + // ); + // + // template <class Iter> + // static void + // set_slice(Container& container, index_type from, + // index_type to, Iter first, Iter last + // ); + // + // static void + // delete_item(Container& container, index_type i); + // + // static void + // delete_slice(Container& container, index_type from, index_type to); + // + // static size_t + // size(Container& container); + // + // template <class T> + // static bool + // contains(Container& container, T const& val); + // + // static index_type + // convert_index(Container& container, PyObject* i); + // + // static index_type + // adjust_index(index_type current, index_type from, + // index_type to, size_type len + // ); + // + // Most of these policies are self explanatory. convert_index and + // adjust_index, however, deserves some explanation. + // + // convert_index converts an Python index into a C++ index that the + // container can handle. For instance, negative indexes in Python, by + // convention, indexes from the right (e.g. C[-1] indexes the rightmost + // element in C). convert_index should handle the necessary conversion + // for the C++ container (e.g. convert -1 to C.size()-1). convert_index + // should also be able to convert the type of the index (A dynamic Python + // type) to the actual type that the C++ container expects. + // + // When a container expands or contracts, held indexes to its elements + // must be adjusted to follow the movement of data. For instance, if + // we erase 3 elements, starting from index 0 from a 5 element vector, + // what used to be at index 4 will now be at index 1: + // + // [a][b][c][d][e] ---> [d][e] + // ^ ^ + // 4 1 + // + // adjust_index takes care of the adjustment. Given a current index, + // the function should return the adjusted index when data in the + // container at index from..to is replaced by *len* elements. + // + + template < + class Container + , class DerivedPolicies + , bool NoProxy = false + , bool NoSlice = false + , class Data = typename Container::value_type + , class Index = typename Container::size_type + , class Key = typename Container::value_type + > + class indexing_suite + : public def_visitor< + indexing_suite< + Container + , DerivedPolicies + , NoProxy + , NoSlice + , Data + , Index + , Key + > > + { + private: + + typedef mpl::or_< + mpl::bool_<NoProxy> + , mpl::not_<is_class<Data> > + , typename mpl::or_< + is_same<Data, std::string> + , is_same<Data, std::complex<float> > + , is_same<Data, std::complex<double> > + , is_same<Data, std::complex<long double> > >::type> + no_proxy; + + typedef detail::container_element<Container, Index, DerivedPolicies> + container_element_t; + +#if BOOST_WORKAROUND(BOOST_MSVC, < 1300) + struct return_policy : return_internal_reference<> {}; +#else + typedef return_internal_reference<> return_policy; +#endif + + typedef typename mpl::if_< + no_proxy + , iterator<Container> + , iterator<Container, return_policy> >::type + def_iterator; + + typedef typename mpl::if_< + no_proxy + , detail::no_proxy_helper< + Container + , DerivedPolicies + , container_element_t + , Index> + , detail::proxy_helper< + Container + , DerivedPolicies + , container_element_t + , Index> >::type + proxy_handler; + + typedef typename mpl::if_< + mpl::bool_<NoSlice> + , detail::no_slice_helper< + Container + , DerivedPolicies + , proxy_handler + , Data + , Index> + , detail::slice_helper< + Container + , DerivedPolicies + , proxy_handler + , Data + , Index> >::type + slice_handler; + + public: + + template <class Class> + void visit(Class& cl) const + { + // Hook into the class_ generic visitation .def function + proxy_handler::register_container_element(); + + cl + .def("__len__", base_size) + .def("__setitem__", &base_set_item) + .def("__delitem__", &base_delete_item) + .def("__getitem__", &base_get_item) + .def("__contains__", &base_contains) + .def("__iter__", def_iterator()) + ; + + DerivedPolicies::extension_def(cl); + } + + template <class Class> + static void + extension_def(Class& cl) + { + // default. + // no more extensions + } + + private: + + static object + base_get_item(back_reference<Container&> container, PyObject* i) + { + if (PySlice_Check(i)) + return slice_handler::base_get_slice( + container.get(), static_cast<PySliceObject*>(static_cast<void*>(i))); + + return proxy_handler::base_get_item_(container, i); + } + + static void + base_set_item(Container& container, PyObject* i, PyObject* v) + { + if (PySlice_Check(i)) + { + slice_handler::base_set_slice(container, + static_cast<PySliceObject*>(static_cast<void*>(i)), v); + } + else + { + extract<Data&> elem(v); + // try if elem is an exact Data + if (elem.check()) + { + DerivedPolicies:: + set_item(container, + DerivedPolicies:: + convert_index(container, i), elem()); + } + else + { + // try to convert elem to Data + extract<Data> elem(v); + if (elem.check()) + { + DerivedPolicies:: + set_item(container, + DerivedPolicies:: + convert_index(container, i), elem()); + } + else + { + PyErr_SetString(PyExc_TypeError, "Invalid assignment"); + throw_error_already_set(); + } + } + } + } + + static void + base_delete_item(Container& container, PyObject* i) + { + if (PySlice_Check(i)) + { + slice_handler::base_delete_slice( + container, static_cast<PySliceObject*>(static_cast<void*>(i))); + return; + } + + Index index = DerivedPolicies::convert_index(container, i); + proxy_handler::base_erase_index(container, index, mpl::bool_<NoSlice>()); + DerivedPolicies::delete_item(container, index); + } + + static size_t + base_size(Container& container) + { + return DerivedPolicies::size(container); + } + + static bool + base_contains(Container& container, PyObject* key) + { + extract<Key const&> x(key); + // try if key is an exact Key type + if (x.check()) + { + return DerivedPolicies::contains(container, x()); + } + else + { + // try to convert key to Key type + extract<Key> x(key); + if (x.check()) + return DerivedPolicies::contains(container, x()); + else + return false; + } + } + }; + +}} // namespace boost::python + +#endif // INDEXING_SUITE_JDG20036_HPP diff --git a/boost/python/suite/indexing/map_indexing_suite.hpp b/boost/python/suite/indexing/map_indexing_suite.hpp new file mode 100644 index 0000000000..7fbad4cace --- /dev/null +++ b/boost/python/suite/indexing/map_indexing_suite.hpp @@ -0,0 +1,181 @@ +// (C) Copyright Joel de Guzman 2003. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef MAP_INDEXING_SUITE_JDG20038_HPP +# define MAP_INDEXING_SUITE_JDG20038_HPP + +# include <boost/python/suite/indexing/indexing_suite.hpp> +# include <boost/python/iterator.hpp> +# include <boost/python/call_method.hpp> +# include <boost/python/tuple.hpp> + +namespace boost { namespace python { + + // Forward declaration + template <class Container, bool NoProxy, class DerivedPolicies> + class map_indexing_suite; + + namespace detail + { + template <class Container, bool NoProxy> + class final_map_derived_policies + : public map_indexing_suite<Container, + NoProxy, final_map_derived_policies<Container, NoProxy> > {}; + } + + // The map_indexing_suite class is a predefined indexing_suite derived + // class for wrapping std::map (and std::map like) classes. It provides + // all the policies required by the indexing_suite (see indexing_suite). + // Example usage: + // + // class X {...}; + // + // ... + // + // class_<std::map<std::string, X> >("XMap") + // .def(map_indexing_suite<std::map<std::string, X> >()) + // ; + // + // By default indexed elements are returned by proxy. This can be + // disabled by supplying *true* in the NoProxy template parameter. + // + template < + class Container, + bool NoProxy = false, + class DerivedPolicies + = detail::final_map_derived_policies<Container, NoProxy> > + class map_indexing_suite + : public indexing_suite< + Container + , DerivedPolicies + , NoProxy + , true + , typename Container::value_type::second_type + , typename Container::key_type + , typename Container::key_type + > + { + public: + + typedef typename Container::value_type value_type; + typedef typename Container::value_type::second_type data_type; + typedef typename Container::key_type key_type; + typedef typename Container::key_type index_type; + typedef typename Container::size_type size_type; + typedef typename Container::difference_type difference_type; + + template <class Class> + static void + extension_def(Class& cl) + { + // Wrap the map's element (value_type) + std::string elem_name = "map_indexing_suite_"; + object class_name(cl.attr("__name__")); + extract<std::string> class_name_extractor(class_name); + elem_name += class_name_extractor(); + elem_name += "_entry"; + + typedef typename mpl::if_< + mpl::and_<is_class<data_type>, mpl::bool_<!NoProxy> > + , return_internal_reference<> + , default_call_policies + >::type get_data_return_policy; + + class_<value_type>(elem_name.c_str()) + .def("__repr__", &DerivedPolicies::print_elem) + .def("data", &DerivedPolicies::get_data, get_data_return_policy()) + .def("key", &DerivedPolicies::get_key) + ; + } + + static object + print_elem(typename Container::value_type const& e) + { + return "(%s, %s)" % python::make_tuple(e.first, e.second); + } + + static + typename mpl::if_< + mpl::and_<is_class<data_type>, mpl::bool_<!NoProxy> > + , data_type& + , data_type + >::type + get_data(typename Container::value_type& e) + { + return e.second; + } + + static typename Container::key_type + get_key(typename Container::value_type& e) + { + return e.first; + } + + static data_type& + get_item(Container& container, index_type i_) + { + typename Container::iterator i = container.find(i_); + if (i == container.end()) + { + PyErr_SetString(PyExc_KeyError, "Invalid key"); + throw_error_already_set(); + } + return i->second; + } + + static void + set_item(Container& container, index_type i, data_type const& v) + { + container[i] = v; + } + + static void + delete_item(Container& container, index_type i) + { + container.erase(i); + } + + static size_t + size(Container& container) + { + return container.size(); + } + + static bool + contains(Container& container, key_type const& key) + { + return container.find(key) != container.end(); + } + + static bool + compare_index(Container& container, index_type a, index_type b) + { + return container.key_comp()(a, b); + } + + static index_type + convert_index(Container& /*container*/, PyObject* i_) + { + extract<key_type const&> i(i_); + if (i.check()) + { + return i(); + } + else + { + extract<key_type> i(i_); + if (i.check()) + return i(); + } + + PyErr_SetString(PyExc_TypeError, "Invalid index type"); + throw_error_already_set(); + return index_type(); + } + }; + +}} // namespace boost::python + +#endif // MAP_INDEXING_SUITE_JDG20038_HPP diff --git a/boost/python/suite/indexing/vector_indexing_suite.hpp b/boost/python/suite/indexing/vector_indexing_suite.hpp new file mode 100644 index 0000000000..34c29ecc6f --- /dev/null +++ b/boost/python/suite/indexing/vector_indexing_suite.hpp @@ -0,0 +1,242 @@ +// (C) Copyright Joel de Guzman 2003. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef VECTOR_INDEXING_SUITE_JDG20036_HPP +# define VECTOR_INDEXING_SUITE_JDG20036_HPP + +# include <boost/python/suite/indexing/indexing_suite.hpp> +# include <boost/python/suite/indexing/container_utils.hpp> +# include <boost/python/iterator.hpp> + +namespace boost { namespace python { + + // Forward declaration + template <class Container, bool NoProxy, class DerivedPolicies> + class vector_indexing_suite; + + namespace detail + { + template <class Container, bool NoProxy> + class final_vector_derived_policies + : public vector_indexing_suite<Container, + NoProxy, final_vector_derived_policies<Container, NoProxy> > {}; + } + + // The vector_indexing_suite class is a predefined indexing_suite derived + // class for wrapping std::vector (and std::vector like) classes. It provides + // all the policies required by the indexing_suite (see indexing_suite). + // Example usage: + // + // class X {...}; + // + // ... + // + // class_<std::vector<X> >("XVec") + // .def(vector_indexing_suite<std::vector<X> >()) + // ; + // + // By default indexed elements are returned by proxy. This can be + // disabled by supplying *true* in the NoProxy template parameter. + // + template < + class Container, + bool NoProxy = false, + class DerivedPolicies + = detail::final_vector_derived_policies<Container, NoProxy> > + class vector_indexing_suite + : public indexing_suite<Container, DerivedPolicies, NoProxy> + { + public: + + typedef typename Container::value_type data_type; + typedef typename Container::value_type key_type; + typedef typename Container::size_type index_type; + typedef typename Container::size_type size_type; + typedef typename Container::difference_type difference_type; + + template <class Class> + static void + extension_def(Class& cl) + { + cl + .def("append", &base_append) + .def("extend", &base_extend) + ; + } + + static + typename mpl::if_< + is_class<data_type> + , data_type& + , data_type + >::type + get_item(Container& container, index_type i) + { + return container[i]; + } + + static object + get_slice(Container& container, index_type from, index_type to) + { + if (from > to) + return object(Container()); + return object(Container(container.begin()+from, container.begin()+to)); + } + + static void + set_item(Container& container, index_type i, data_type const& v) + { + container[i] = v; + } + + static void + set_slice(Container& container, index_type from, + index_type to, data_type const& v) + { + if (from > to) { + return; + } + else { + container.erase(container.begin()+from, container.begin()+to); + container.insert(container.begin()+from, v); + } + } + + template <class Iter> + static void + set_slice(Container& container, index_type from, + index_type to, Iter first, Iter last) + { + if (from > to) { + container.insert(container.begin()+from, first, last); + } + else { + container.erase(container.begin()+from, container.begin()+to); + container.insert(container.begin()+from, first, last); + } + } + + static void + delete_item(Container& container, index_type i) + { + container.erase(container.begin()+i); + } + + static void + delete_slice(Container& container, index_type from, index_type to) + { + if (from > to) { + // A null-op. + return; + } + container.erase(container.begin()+from, container.begin()+to); + } + + static size_t + size(Container& container) + { + return container.size(); + } + + static bool + contains(Container& container, key_type const& key) + { + return std::find(container.begin(), container.end(), key) + != container.end(); + } + + static index_type + get_min_index(Container& /*container*/) + { + return 0; + } + + static index_type + get_max_index(Container& container) + { + return container.size(); + } + + static bool + compare_index(Container& /*container*/, index_type a, index_type b) + { + return a < b; + } + + static index_type + convert_index(Container& container, PyObject* i_) + { + extract<long> i(i_); + if (i.check()) + { + long index = i(); + if (index < 0) + index += DerivedPolicies::size(container); + if (index >= long(container.size()) || index < 0) + { + PyErr_SetString(PyExc_IndexError, "Index out of range"); + throw_error_already_set(); + } + return index; + } + + PyErr_SetString(PyExc_TypeError, "Invalid index type"); + throw_error_already_set(); + return index_type(); + } + + static void + append(Container& container, data_type const& v) + { + container.push_back(v); + } + + template <class Iter> + static void + extend(Container& container, Iter first, Iter last) + { + container.insert(container.end(), first, last); + } + + private: + + static void + base_append(Container& container, object v) + { + extract<data_type&> elem(v); + // try if elem is an exact Data + if (elem.check()) + { + DerivedPolicies::append(container, elem()); + } + else + { + // try to convert elem to data_type + extract<data_type> elem(v); + if (elem.check()) + { + DerivedPolicies::append(container, elem()); + } + else + { + PyErr_SetString(PyExc_TypeError, + "Attempting to append an invalid type"); + throw_error_already_set(); + } + } + } + + static void + base_extend(Container& container, object v) + { + std::vector<data_type> temp; + container_utils::extend_container(temp, v); + DerivedPolicies::extend(container, temp.begin(), temp.end()); + } + }; + +}} // namespace boost::python + +#endif // VECTOR_INDEXING_SUITE_JDG20036_HPP diff --git a/boost/python/tag.hpp b/boost/python/tag.hpp new file mode 100644 index 0000000000..ccff9f1a17 --- /dev/null +++ b/boost/python/tag.hpp @@ -0,0 +1,18 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef TAG_DWA2002720_HPP +# define TAG_DWA2002720_HPP + +# include <boost/python/detail/prefix.hpp> + +namespace boost { namespace python { + +// used only to prevent argument-dependent lookup from finding the +// wrong function in some cases. Cheaper than qualification. +enum tag_t { tag }; + +}} // namespace boost::python + +#endif // TAG_DWA2002720_HPP diff --git a/boost/python/to_python_converter.hpp b/boost/python/to_python_converter.hpp new file mode 100644 index 0000000000..378d159e97 --- /dev/null +++ b/boost/python/to_python_converter.hpp @@ -0,0 +1,99 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef TO_PYTHON_CONVERTER_DWA200221_HPP +# define TO_PYTHON_CONVERTER_DWA200221_HPP + +# include <boost/python/detail/prefix.hpp> + +# include <boost/python/converter/registry.hpp> +# include <boost/python/converter/as_to_python_function.hpp> +#ifndef BOOST_PYTHON_NO_PY_SIGNATURES +# include <boost/python/converter/pytype_function.hpp> +#endif +# include <boost/python/type_id.hpp> + +namespace boost { namespace python { + +#if 0 //get_pytype member detection +namespace detail +{ + typedef char yes_type; + typedef struct {char a[2]; } no_type; + template<PyTypeObject const * (*f)()> struct test_get_pytype1 { }; + template<PyTypeObject * (*f)()> struct test_get_pytype2 { }; + + template<class T> yes_type tester(test_get_pytype1<&T::get_pytype>*); + + template<class T> yes_type tester(test_get_pytype2<&T::get_pytype>*); + + template<class T> no_type tester(...); + + template<class T> + struct test_get_pytype_base + { + BOOST_STATIC_CONSTANT(bool, value= (sizeof(detail::tester<T>(0)) == sizeof(yes_type))); + }; + + template<class T> + struct test_get_pytype : boost::mpl::bool_<test_get_pytype_base<T>::value> + { + }; + +} +#endif + +template < class T, class Conversion, bool has_get_pytype=false > +struct to_python_converter +{ +#ifndef BOOST_PYTHON_NO_PY_SIGNATURES +#if 0 //defined _MSC_VER && _MSC_VER >=1310 + //probably other compilers could come here as well + typedef typename detail::test_get_pytype<Conversion> HasGetPytype; +#else + typedef boost::mpl::bool_<has_get_pytype> HasGetPytype; +#endif + + static PyTypeObject const* get_pytype_1(boost::mpl::true_ *) + { + return Conversion::get_pytype(); + } + + static PyTypeObject const* get_pytype_1(boost::mpl::false_ *) + { + return 0; + } + static PyTypeObject const* get_pytype_impl() + { + return get_pytype_1((HasGetPytype*)0); + } +#endif + + to_python_converter(); +}; + +// +// implementation +// + +template <class T, class Conversion ,bool has_get_pytype> +to_python_converter<T,Conversion, has_get_pytype>::to_python_converter() +{ + typedef converter::as_to_python_function< + T, Conversion + > normalized; + + converter::registry::insert( + &normalized::convert + , type_id<T>() +#ifndef BOOST_PYTHON_NO_PY_SIGNATURES + , &get_pytype_impl +#endif + ); +} + +}} // namespace boost::python + +#endif // TO_PYTHON_CONVERTER_DWA200221_HPP + diff --git a/boost/python/to_python_indirect.hpp b/boost/python/to_python_indirect.hpp new file mode 100644 index 0000000000..23ad026319 --- /dev/null +++ b/boost/python/to_python_indirect.hpp @@ -0,0 +1,113 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef TO_PYTHON_INDIRECT_DWA200221_HPP +# define TO_PYTHON_INDIRECT_DWA200221_HPP + +# include <boost/python/detail/prefix.hpp> + +# include <boost/python/object/pointer_holder.hpp> +# include <boost/python/object/make_ptr_instance.hpp> + +# include <boost/python/detail/none.hpp> + +#ifndef BOOST_PYTHON_NO_PY_SIGNATURES +# include <boost/python/converter/pytype_function.hpp> +#endif + +# include <boost/python/refcount.hpp> + +# include <boost/type_traits/is_pointer.hpp> +# include <boost/type_traits/is_polymorphic.hpp> + +# include <boost/mpl/bool.hpp> + +# if defined(__ICL) && __ICL < 600 +# include <boost/shared_ptr.hpp> +# else +# include <memory> +# endif + +namespace boost { namespace python { + +template <class T, class MakeHolder> +struct to_python_indirect +{ + template <class U> + inline PyObject* + operator()(U const& ref) const + { + return this->execute(const_cast<U&>(ref), is_pointer<U>()); + } +#ifndef BOOST_PYTHON_NO_PY_SIGNATURES + inline PyTypeObject const* + get_pytype()const + { + return converter::registered_pytype<T>::get_pytype(); + } +#endif + private: + template <class U> + inline PyObject* execute(U* ptr, mpl::true_) const + { + // No special NULL treatment for references + if (ptr == 0) + return python::detail::none(); + else + return this->execute(*ptr, mpl::false_()); + } + + template <class U> + inline PyObject* execute(U const& x, mpl::false_) const + { + U* const p = &const_cast<U&>(x); + if (is_polymorphic<U>::value) + { + if (PyObject* o = detail::wrapper_base_::owner(p)) + return incref(o); + } + return MakeHolder::execute(p); + } +}; + +// +// implementations +// +namespace detail +{ + struct make_owning_holder + { + template <class T> + static PyObject* execute(T* p) + { + // can't use auto_ptr with Intel 5 and VC6 Dinkum library + // for some reason. We get link errors against the auto_ptr + // copy constructor. +# if defined(__ICL) && __ICL < 600 + typedef boost::shared_ptr<T> smart_pointer; +# else + typedef std::auto_ptr<T> smart_pointer; +# endif + typedef objects::pointer_holder<smart_pointer, T> holder_t; + + smart_pointer ptr(const_cast<T*>(p)); + return objects::make_ptr_instance<T, holder_t>::execute(ptr); + } + }; + + struct make_reference_holder + { + template <class T> + static PyObject* execute(T* p) + { + typedef objects::pointer_holder<T*, T> holder_t; + T* q = const_cast<T*>(p); + return objects::make_ptr_instance<T, holder_t>::execute(q); + } + }; +} + +}} // namespace boost::python + +#endif // TO_PYTHON_INDIRECT_DWA200221_HPP diff --git a/boost/python/to_python_value.hpp b/boost/python/to_python_value.hpp new file mode 100644 index 0000000000..a48948d256 --- /dev/null +++ b/boost/python/to_python_value.hpp @@ -0,0 +1,176 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef TO_PYTHON_VALUE_DWA200221_HPP +# define TO_PYTHON_VALUE_DWA200221_HPP + +# include <boost/python/detail/prefix.hpp> + +# include <boost/python/refcount.hpp> +# include <boost/python/tag.hpp> +# include <boost/python/handle.hpp> + +# include <boost/python/converter/registry.hpp> +# include <boost/python/converter/registered.hpp> +# include <boost/python/converter/builtin_converters.hpp> +# include <boost/python/converter/object_manager.hpp> +# include <boost/python/converter/shared_ptr_to_python.hpp> + +# include <boost/python/detail/value_is_shared_ptr.hpp> +# include <boost/python/detail/value_arg.hpp> + +# include <boost/type_traits/transform_traits.hpp> + +# include <boost/mpl/if.hpp> +# include <boost/mpl/or.hpp> +# include <boost/type_traits/is_const.hpp> + +namespace boost { namespace python { + +namespace detail +{ +#ifndef BOOST_PYTHON_NO_PY_SIGNATURES + +template <bool is_const_ref> +struct object_manager_get_pytype +{ + template <class U> + static PyTypeObject const* get( U& (*)() =0) + { + return converter::object_manager_traits<U>::get_pytype(); + } +}; + +template <> +struct object_manager_get_pytype<true> +{ + template <class U> + static PyTypeObject const* get( U const& (*)() =0) + { + return converter::object_manager_traits<U>::get_pytype(); + } +}; + +#endif + + template <class T> + struct object_manager_to_python_value + { + typedef typename value_arg<T>::type argument_type; + + PyObject* operator()(argument_type) const; +#ifndef BOOST_PYTHON_NO_PY_SIGNATURES + typedef boost::mpl::bool_<is_handle<T>::value> is_t_handle; + typedef boost::detail::indirect_traits::is_reference_to_const<T> is_t_const; + PyTypeObject const* get_pytype() const { + return get_pytype_aux((is_t_handle*)0); + } + + inline static PyTypeObject const* get_pytype_aux(mpl::true_*) {return converter::object_manager_traits<T>::get_pytype();} + + inline static PyTypeObject const* get_pytype_aux(mpl::false_* ) + { + return object_manager_get_pytype<is_t_const::value>::get((T(*)())0); + } + +#endif + + // This information helps make_getter() decide whether to try to + // return an internal reference or not. I don't like it much, + // but it will have to serve for now. + BOOST_STATIC_CONSTANT(bool, uses_registry = false); + }; + + + template <class T> + struct registry_to_python_value + { + typedef typename value_arg<T>::type argument_type; + + PyObject* operator()(argument_type) const; +#ifndef BOOST_PYTHON_NO_PY_SIGNATURES + PyTypeObject const* get_pytype() const {return converter::registered<T>::converters.to_python_target_type();} +#endif + + // This information helps make_getter() decide whether to try to + // return an internal reference or not. I don't like it much, + // but it will have to serve for now. + BOOST_STATIC_CONSTANT(bool, uses_registry = true); + }; + + template <class T> + struct shared_ptr_to_python_value + { + typedef typename value_arg<T>::type argument_type; + + PyObject* operator()(argument_type) const; +#ifndef BOOST_PYTHON_NO_PY_SIGNATURES + PyTypeObject const* get_pytype() const {return get_pytype((boost::type<argument_type>*)0);} +#endif + // This information helps make_getter() decide whether to try to + // return an internal reference or not. I don't like it much, + // but it will have to serve for now. + BOOST_STATIC_CONSTANT(bool, uses_registry = false); + private: +#ifndef BOOST_PYTHON_NO_PY_SIGNATURES + template <class U> + PyTypeObject const* get_pytype(boost::type<shared_ptr<U> &> *) const {return converter::registered<U>::converters.to_python_target_type();} + template <class U> + PyTypeObject const* get_pytype(boost::type<const shared_ptr<U> &> *) const {return converter::registered<U>::converters.to_python_target_type();} +#endif + }; +} + +template <class T> +struct to_python_value + : mpl::if_< + detail::value_is_shared_ptr<T> + , detail::shared_ptr_to_python_value<T> + , typename mpl::if_< + mpl::or_< + converter::is_object_manager<T> + , converter::is_reference_to_object_manager<T> + > + , detail::object_manager_to_python_value<T> + , detail::registry_to_python_value<T> + >::type + >::type +{ +}; + +// +// implementation +// +namespace detail +{ + template <class T> + inline PyObject* registry_to_python_value<T>::operator()(argument_type x) const + { + typedef converter::registered<argument_type> r; +# if BOOST_WORKAROUND(__GNUC__, < 3) + // suppresses an ICE, somehow + (void)r::converters; +# endif + return converter::registered<argument_type>::converters.to_python(&x); + } + + template <class T> + inline PyObject* object_manager_to_python_value<T>::operator()(argument_type x) const + { + return python::upcast<PyObject>( + python::xincref( + get_managed_object(x, tag)) + ); + } + + template <class T> + inline PyObject* shared_ptr_to_python_value<T>::operator()(argument_type x) const + { + return converter::shared_ptr_to_python(x); + } +} + +}} // namespace boost::python + +#endif // TO_PYTHON_VALUE_DWA200221_HPP diff --git a/boost/python/tuple.hpp b/boost/python/tuple.hpp new file mode 100644 index 0000000000..babfb63f1e --- /dev/null +++ b/boost/python/tuple.hpp @@ -0,0 +1,70 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef TUPLE_20020706_HPP +#define TUPLE_20020706_HPP + +# include <boost/python/detail/prefix.hpp> + +#include <boost/python/object.hpp> +#include <boost/python/converter/pytype_object_mgr_traits.hpp> +#include <boost/preprocessor/enum_params.hpp> +#include <boost/preprocessor/repetition/enum_binary_params.hpp> + +namespace boost { namespace python { + +namespace detail +{ + struct BOOST_PYTHON_DECL tuple_base : object + { + protected: + tuple_base(); + tuple_base(object_cref sequence); + + BOOST_PYTHON_FORWARD_OBJECT_CONSTRUCTORS(tuple_base, object) + + private: + static detail::new_reference call(object const&); + }; +} + +class tuple : public detail::tuple_base +{ + typedef detail::tuple_base base; + public: + tuple() {} + + template <class T> + explicit tuple(T const& sequence) + : base(object(sequence)) + { + } + + public: // implementation detail -- for internal use only + BOOST_PYTHON_FORWARD_OBJECT_CONSTRUCTORS(tuple, base) +}; + +// +// Converter Specializations // $$$ JDG $$$ moved here to prevent +// // G++ bug complaining specialization + // provided after instantiation +namespace converter +{ + template <> + struct object_manager_traits<tuple> + : pytype_object_manager_traits<&PyTuple_Type,tuple> + { + }; +} + +// for completeness +inline tuple make_tuple() { return tuple(); } + +# define BOOST_PP_ITERATION_PARAMS_1 (3, (1, BOOST_PYTHON_MAX_ARITY, <boost/python/detail/make_tuple.hpp>)) +# include BOOST_PP_ITERATE() + +}} // namespace boost::python + +#endif + diff --git a/boost/python/type_id.hpp b/boost/python/type_id.hpp new file mode 100644 index 0000000000..4a5727d514 --- /dev/null +++ b/boost/python/type_id.hpp @@ -0,0 +1,192 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef TYPE_ID_DWA2002517_HPP +# define TYPE_ID_DWA2002517_HPP + +# include <boost/python/detail/prefix.hpp> + +# include <boost/python/detail/msvc_typeinfo.hpp> +# include <boost/operators.hpp> +# include <typeinfo> +# include <cstring> +# include <ostream> +# include <boost/static_assert.hpp> +# include <boost/detail/workaround.hpp> +# include <boost/type_traits/same_traits.hpp> +# include <boost/type_traits/broken_compiler_spec.hpp> + +# ifndef BOOST_PYTHON_HAVE_GCC_CP_DEMANGLE +# if defined(__GNUC__) \ + && ((__GNUC__ > 3) || ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 1))) \ + && !defined(__EDG_VERSION__) +# define BOOST_PYTHON_HAVE_GCC_CP_DEMANGLE +# endif +# endif + +namespace boost { namespace python { + +// for this compiler at least, cross-shared-library type_info +// comparisons don't work, so use typeid(x).name() instead. It's not +// yet clear what the best default strategy is. +# if (defined(__GNUC__) && __GNUC__ >= 3) \ + || defined(_AIX) \ + || ( defined(__sgi) && defined(__host_mips)) \ + || (defined(__hpux) && defined(__HP_aCC)) \ + || (defined(linux) && defined(__INTEL_COMPILER) && defined(__ICC)) +# define BOOST_PYTHON_TYPE_ID_NAME +# endif + +#ifdef BOOST_PYTHON_HAVE_GCC_CP_DEMANGLE +// Runtime detection of broken cxxabi::__cxa_demangle versions, +// to avoid #ifdef clutter. +bool cxxabi_cxa_demangle_is_broken(); +#define BOOST_PYTHON_HAVE_CXXABI_CXA_DEMANGLE_IS_BROKEN +#endif + +// type ids which represent the same information as std::type_info +// (i.e. the top-level reference and cv-qualifiers are stripped), but +// which works across shared libraries. +struct type_info : private totally_ordered<type_info> +{ + inline type_info(std::type_info const& = typeid(void)); + + inline bool operator<(type_info const& rhs) const; + inline bool operator==(type_info const& rhs) const; + + char const* name() const; + friend BOOST_PYTHON_DECL std::ostream& operator<<( + std::ostream&, type_info const&); + + private: // data members +# ifdef BOOST_PYTHON_TYPE_ID_NAME + typedef char const* base_id_t; +# else + typedef std::type_info const* base_id_t; +# endif + + base_id_t m_base_type; +}; + +# ifdef BOOST_NO_EXPLICIT_FUNCTION_TEMPLATE_ARGUMENTS +# define BOOST_PYTHON_EXPLICIT_TT_DEF(T) ::boost::type<T>* +# else +# define BOOST_PYTHON_EXPLICIT_TT_DEF(T) +# endif + +template <class T> +inline type_info type_id(BOOST_EXPLICIT_TEMPLATE_TYPE(T)) +{ + return type_info( +# if !defined(_MSC_VER) \ + || (!BOOST_WORKAROUND(BOOST_MSVC, <= 1300) \ + && !BOOST_WORKAROUND(BOOST_INTEL_CXX_VERSION, <= 700)) + typeid(T) +# else // strip the decoration which msvc and Intel mistakenly leave in + python::detail::msvc_typeid((boost::type<T>*)0) +# endif + ); +} + +# if (defined(__EDG_VERSION__) && __EDG_VERSION__ < 245) \ + || (defined(__sgi) && defined(_COMPILER_VERSION) && _COMPILER_VERSION <= 744) +// Older EDG-based compilers seems to mistakenly distinguish "int" from +// "signed int", etc., but only in typeid() expressions. However +// though int == signed int, the "signed" decoration is propagated +// down into template instantiations. Explicit specialization stops +// that from taking hold. + +# define BOOST_PYTHON_SIGNED_INTEGRAL_TYPE_ID(T) \ +template <> \ +inline type_info type_id<T>(BOOST_PYTHON_EXPLICIT_TT_DEF(T)) \ +{ \ + return type_info(typeid(T)); \ +} + +BOOST_PYTHON_SIGNED_INTEGRAL_TYPE_ID(short) +BOOST_PYTHON_SIGNED_INTEGRAL_TYPE_ID(int) +BOOST_PYTHON_SIGNED_INTEGRAL_TYPE_ID(long) +// using Python's macro instead of Boost's - we don't seem to get the +// config right all the time. +# ifdef HAVE_LONG_LONG +BOOST_PYTHON_SIGNED_INTEGRAL_TYPE_ID(long long) +# endif +# undef BOOST_PYTHON_SIGNED_INTEGRAL_TYPE_ID +# endif + +// +inline type_info::type_info(std::type_info const& id) + : m_base_type( +# ifdef BOOST_PYTHON_TYPE_ID_NAME + id.name() +# else + &id +# endif + ) +{ +} + +inline bool type_info::operator<(type_info const& rhs) const +{ +# ifdef BOOST_PYTHON_TYPE_ID_NAME + return std::strcmp(m_base_type, rhs.m_base_type) < 0; +# else + return m_base_type->before(*rhs.m_base_type); +# endif +} + +inline bool type_info::operator==(type_info const& rhs) const +{ +# ifdef BOOST_PYTHON_TYPE_ID_NAME + return !std::strcmp(m_base_type, rhs.m_base_type); +# else + return *m_base_type == *rhs.m_base_type; +# endif +} + +# ifdef BOOST_PYTHON_HAVE_GCC_CP_DEMANGLE +namespace detail +{ + BOOST_PYTHON_DECL char const* gcc_demangle(char const*); +} +# endif + +inline char const* type_info::name() const +{ + char const* raw_name + = m_base_type +# ifndef BOOST_PYTHON_TYPE_ID_NAME + ->name() +# endif + ; + +# ifdef BOOST_PYTHON_HAVE_GCC_CP_DEMANGLE + return detail::gcc_demangle(raw_name); +# else + return raw_name; +# endif +} + + +BOOST_PYTHON_DECL std::ostream& operator<<(std::ostream&, type_info const&); + +# if !BOOST_WORKAROUND(BOOST_MSVC, == 1200) +template<> +inline type_info type_id<void>(BOOST_PYTHON_EXPLICIT_TT_DEF(void)) +{ + return type_info (typeid (void *)); +} +# ifndef BOOST_NO_CV_VOID_SPECIALIZATIONS +template<> +inline type_info type_id<const volatile void>(BOOST_PYTHON_EXPLICIT_TT_DEF(const volatile void)) +{ + return type_info (typeid (void *)); +} +# endif + +# endif + +}} // namespace boost::python + +#endif // TYPE_ID_DWA2002517_HPP diff --git a/boost/python/with_custodian_and_ward.hpp b/boost/python/with_custodian_and_ward.hpp new file mode 100644 index 0000000000..9399478f23 --- /dev/null +++ b/boost/python/with_custodian_and_ward.hpp @@ -0,0 +1,125 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef WITH_CUSTODIAN_AND_WARD_DWA2002131_HPP +# define WITH_CUSTODIAN_AND_WARD_DWA2002131_HPP + +# include <boost/python/detail/prefix.hpp> + +# include <boost/python/default_call_policies.hpp> +# include <boost/python/object/life_support.hpp> +# include <algorithm> + +namespace boost { namespace python { + +namespace detail +{ + template <std::size_t N> + struct get_prev + { + template <class ArgumentPackage> + static PyObject* execute(ArgumentPackage const& args, PyObject* = 0) + { + int const pre_n = static_cast<int>(N) - 1; // separate line is gcc-2.96 workaround + return detail::get(mpl::int_<pre_n>(), args); + } + }; + template <> + struct get_prev<0> + { + template <class ArgumentPackage> + static PyObject* execute(ArgumentPackage const&, PyObject* zeroth) + { + return zeroth; + } + }; +} +template < + std::size_t custodian + , std::size_t ward + , class BasePolicy_ = default_call_policies +> +struct with_custodian_and_ward : BasePolicy_ +{ + BOOST_STATIC_ASSERT(custodian != ward); + BOOST_STATIC_ASSERT(custodian > 0); + BOOST_STATIC_ASSERT(ward > 0); + + template <class ArgumentPackage> + static bool precall(ArgumentPackage const& args_) + { + unsigned arity_ = detail::arity(args_); + if (custodian > arity_ || ward > arity_) + { + PyErr_SetString( + PyExc_IndexError + , "boost::python::with_custodian_and_ward: argument index out of range" + ); + return false; + } + + PyObject* patient = detail::get_prev<ward>::execute(args_); + PyObject* nurse = detail::get_prev<custodian>::execute(args_); + + PyObject* life_support = python::objects::make_nurse_and_patient(nurse, patient); + if (life_support == 0) + return false; + + bool result = BasePolicy_::precall(args_); + + if (!result) { + Py_DECREF(life_support); + } + + return result; + } +}; + +template <std::size_t custodian, std::size_t ward, class BasePolicy_ = default_call_policies> +struct with_custodian_and_ward_postcall : BasePolicy_ +{ + BOOST_STATIC_ASSERT(custodian != ward); + + template <class ArgumentPackage> + static PyObject* postcall(ArgumentPackage const& args_, PyObject* result) + { + std::size_t arity_ = detail::arity(args_); +#if BOOST_WORKAROUND(BOOST_MSVC, < 1300) + if ( custodian > arity_ || ward > arity_ ) +#else + // check if either custodian or ward exceeds the arity + // (this weird formulation avoids "always false" warnings + // for arity_ = 0) + if ( (std::max)(custodian, ward) > arity_ ) +#endif + { + PyErr_SetString( + PyExc_IndexError + , "boost::python::with_custodian_and_ward_postcall: argument index out of range" + ); + return 0; + } + + PyObject* patient = detail::get_prev<ward>::execute(args_, result); + PyObject* nurse = detail::get_prev<custodian>::execute(args_, result); + + if (nurse == 0) return 0; + + result = BasePolicy_::postcall(args_, result); + if (result == 0) + return 0; + + if (python::objects::make_nurse_and_patient(nurse, patient) == 0) + { + Py_XDECREF(result); + return 0; + } + return result; + } +}; + + +}} // namespace boost::python + +#endif // WITH_CUSTODIAN_AND_WARD_DWA2002131_HPP diff --git a/boost/python/wrapper.hpp b/boost/python/wrapper.hpp new file mode 100644 index 0000000000..166c8e2327 --- /dev/null +++ b/boost/python/wrapper.hpp @@ -0,0 +1,35 @@ +// Copyright David Abrahams 2004. Distributed under the Boost +// Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +#ifndef WRAPPER_DWA2004720_HPP +# define WRAPPER_DWA2004720_HPP + +# include <boost/python/detail/wrapper_base.hpp> +# include <boost/python/override.hpp> +# include <boost/python/converter/registered.hpp> +# include <boost/python/detail/sfinae.hpp> + +namespace boost { namespace python { + +template <class T> +class wrapper : public detail::wrapper_base +{ + public: + // Do not touch this implementation detail! + typedef T _wrapper_wrapped_type_; + + protected: + override get_override(char const* name) const + { + typedef detail::wrapper_base base; + converter::registration const& r + = converter::registered<T>::converters; + PyTypeObject* type = r.get_class_object(); + + return this->base::get_override(name, type); + } +}; + +}} // namespace boost::python + +#endif // WRAPPER_DWA2004720_HPP |