caller.hpp

来自「Boost provides free peer-reviewed portab」· HPP 代码 · 共 260 行

HPP
260
字号
#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// implementationtypedef 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_SIGNATUREStemplate <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 

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?