sl@0: #if !defined(BOOST_PP_IS_ITERATING) sl@0: sl@0: // Copyright David Abrahams 2002. sl@0: // Distributed under the Boost Software License, Version 1.0. (See sl@0: // accompanying file LICENSE_1_0.txt or copy at sl@0: // http://www.boost.org/LICENSE_1_0.txt) sl@0: sl@0: # ifndef CALLER_DWA20021121_HPP sl@0: # define CALLER_DWA20021121_HPP sl@0: sl@0: # include sl@0: # include sl@0: sl@0: # include sl@0: # include sl@0: # include sl@0: sl@0: # include sl@0: # include sl@0: sl@0: # include sl@0: # include sl@0: # include sl@0: # include sl@0: # include sl@0: # include sl@0: # include sl@0: sl@0: # include sl@0: sl@0: # include sl@0: # include sl@0: sl@0: # include sl@0: # include sl@0: # include sl@0: # include sl@0: # include sl@0: # include sl@0: # include sl@0: sl@0: namespace boost { namespace python { namespace detail { sl@0: sl@0: template sl@0: inline PyObject* get(mpl::int_, PyObject* const& args_) sl@0: { sl@0: return PyTuple_GET_ITEM(args_,N); sl@0: } sl@0: sl@0: inline unsigned arity(PyObject* const& args_) sl@0: { sl@0: return PyTuple_GET_SIZE(args_); sl@0: } sl@0: sl@0: // This "result converter" is really just used as sl@0: // a dispatch tag to invoke(...), selecting the appropriate sl@0: // implementation sl@0: typedef int void_result_to_python; sl@0: sl@0: // Given a model of CallPolicies and a C++ result type, this sl@0: // metafunction selects the appropriate converter to use for sl@0: // converting the result to python. sl@0: template sl@0: struct select_result_converter sl@0: : mpl::eval_if< sl@0: is_same sl@0: , mpl::identity sl@0: , mpl::apply1 sl@0: > sl@0: { sl@0: }; sl@0: sl@0: template sl@0: inline ResultConverter create_result_converter( sl@0: ArgPackage const& args_ sl@0: , ResultConverter* sl@0: , converter::context_result_converter* sl@0: ) sl@0: { sl@0: return ResultConverter(args_); sl@0: } sl@0: sl@0: template sl@0: inline ResultConverter create_result_converter( sl@0: ArgPackage const& sl@0: , ResultConverter* sl@0: , ... sl@0: ) sl@0: { sl@0: return ResultConverter(); sl@0: } sl@0: sl@0: template struct caller_arity; sl@0: sl@0: template sl@0: struct caller; sl@0: sl@0: # define BOOST_PYTHON_NEXT(init,name,n) \ sl@0: typedef BOOST_PP_IF(n,typename mpl::next< BOOST_PP_CAT(name,BOOST_PP_DEC(n)) >::type, init) name##n; sl@0: sl@0: # define BOOST_PYTHON_ARG_CONVERTER(n) \ sl@0: BOOST_PYTHON_NEXT(typename mpl::next::type, arg_iter,n) \ sl@0: typedef arg_from_python c_t##n; \ sl@0: c_t##n c##n(get(mpl::int_(), inner_args)); \ sl@0: if (!c##n.convertible()) \ sl@0: return 0; sl@0: sl@0: # define BOOST_PP_ITERATION_PARAMS_1 \ sl@0: (3, (0, BOOST_PYTHON_MAX_ARITY + 1, )) sl@0: # include BOOST_PP_ITERATE() sl@0: sl@0: # undef BOOST_PYTHON_ARG_CONVERTER sl@0: # undef BOOST_PYTHON_NEXT sl@0: sl@0: // A metafunction returning the base class used for caller. sl@0: template sl@0: struct caller_base_select sl@0: { sl@0: enum { arity = mpl::size::value - 1 }; sl@0: typedef typename caller_arity::template impl type; sl@0: }; sl@0: sl@0: // A function object type which wraps C++ objects as Python callable sl@0: // objects. sl@0: // sl@0: // Template Arguments: sl@0: // sl@0: // F - sl@0: // the C++ `function object' that will be called. Might sl@0: // actually be any data for which an appropriate invoke_tag() can sl@0: // be generated. invoke(...) takes care of the actual invocation syntax. sl@0: // sl@0: // CallPolicies - sl@0: // The precall, postcall, and what kind of resultconverter to sl@0: // generate for mpl::front::type sl@0: // sl@0: // Sig - sl@0: // The `intended signature' of the function. An MPL sequence sl@0: // beginning with a result type and continuing with a list of sl@0: // argument types. sl@0: template sl@0: struct caller sl@0: : caller_base_select::type sl@0: { sl@0: typedef typename caller_base_select< sl@0: F,CallPolicies,Sig sl@0: >::type base; sl@0: sl@0: typedef PyObject* result_type; sl@0: sl@0: caller(F f, CallPolicies p) : base(f,p) {} sl@0: sl@0: }; sl@0: sl@0: }}} // namespace boost::python::detail sl@0: sl@0: # endif // CALLER_DWA20021121_HPP sl@0: sl@0: #else sl@0: sl@0: # define N BOOST_PP_ITERATION() sl@0: sl@0: template <> sl@0: struct caller_arity sl@0: { sl@0: template sl@0: struct impl sl@0: { sl@0: impl(F f, Policies p) : m_data(f,p) {} sl@0: sl@0: PyObject* operator()(PyObject* args_, PyObject*) // eliminate sl@0: // this sl@0: // trailing sl@0: // keyword dict sl@0: { sl@0: typedef typename mpl::begin::type first; sl@0: typedef typename first::type result_t; sl@0: typedef typename select_result_converter::type result_converter; sl@0: typedef typename Policies::argument_package argument_package; sl@0: sl@0: argument_package inner_args(args_); sl@0: sl@0: # if N sl@0: # define BOOST_PP_LOCAL_MACRO(i) BOOST_PYTHON_ARG_CONVERTER(i) sl@0: # define BOOST_PP_LOCAL_LIMITS (0, N-1) sl@0: # include BOOST_PP_LOCAL_ITERATE() sl@0: # endif sl@0: // all converters have been checked. Now we can do the sl@0: // precall part of the policy sl@0: if (!m_data.second().precall(inner_args)) sl@0: return 0; sl@0: sl@0: PyObject* result = detail::invoke( sl@0: detail::invoke_tag() sl@0: , create_result_converter(args_, (result_converter*)0, (result_converter*)0) sl@0: , m_data.first() sl@0: BOOST_PP_ENUM_TRAILING_PARAMS(N, c) sl@0: ); sl@0: sl@0: return m_data.second().postcall(inner_args, result); sl@0: } sl@0: sl@0: static unsigned min_arity() { return N; } sl@0: sl@0: static signature_element const* signature() sl@0: { sl@0: return detail::signature::elements(); sl@0: } sl@0: sl@0: private: sl@0: compressed_pair m_data; sl@0: }; sl@0: }; sl@0: sl@0: sl@0: sl@0: #endif // BOOST_PP_IS_ITERATING sl@0: sl@0: