260 lines
		
	
	
		
			8.1 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
		
		
			
		
	
	
			260 lines
		
	
	
		
			8.1 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
|   | #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  | ||
|  | 
 | ||
|  | 
 |