diff options
Diffstat (limited to 'boost/python/make_constructor.hpp')
-rw-r--r-- | boost/python/make_constructor.hpp | 290 |
1 files changed, 290 insertions, 0 deletions
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 |