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