99# ifndef CALLER_DWA20021121_HPP
1010# define CALLER_DWA20021121_HPP
1111
12- # include < boost/compressed_pair.hpp>
13-
14- # include < boost/mpl/apply.hpp>
15- # include < boost/mpl/if.hpp>
16- # include < boost/mpl/size.hpp>
17- # include < boost/mpl/at.hpp>
18- # include < boost/type_traits/is_same.hpp>
19-
2012# include < boost/python/type_id.hpp>
2113# include < boost/python/handle.hpp>
2214
2517# include < boost/python/detail/preprocessor.hpp>
2618
2719# include < boost/python/arg_from_python.hpp>
20+ # include < boost/python/converter/context_result_converter.hpp>
2821
2922# include < boost/preprocessor/iterate.hpp>
3023# include < boost/preprocessor/cat.hpp>
3427# include < boost/preprocessor/repetition/enum_trailing_params.hpp>
3528# include < boost/preprocessor/repetition/repeat.hpp>
3629
30+ # include < boost/compressed_pair.hpp>
31+
32+ # include < boost/type_traits/is_same.hpp>
33+ # include < boost/type_traits/is_convertible.hpp>
34+
35+ # include < boost/mpl/apply.hpp>
36+ # include < boost/mpl/apply_if.hpp>
37+ # include < boost/mpl/identity.hpp>
38+ # include < boost/mpl/size.hpp>
39+ # include < boost/mpl/at.hpp>
40+ # include < boost/mpl/int.hpp>
41+
3742namespace boost { namespace python { namespace detail {
3843
44+ # if 0 // argpkg
45+ template <class N >
46+ inline PyObject* get (N, PyObject* const & args_)
47+ {
48+ return PyTuple_GET_ITEM (args_,N::value);
49+ }
50+ # else
51+ template <unsigned N>
52+ inline PyObject* get (PyObject* const & args_ BOOST_APPEND_EXPLICIT_TEMPLATE_NON_TYPE (unsigned ,N))
53+ {
54+ return PyTuple_GET_ITEM (args_,N);
55+ }
56+ # endif
57+
58+ inline unsigned arity (PyObject* const & args_)
59+ {
60+ return PyTuple_GET_SIZE (args_);
61+ }
62+
3963// This "result converter" is really just used as
4064// a dispatch tag to invoke(...), selecting the appropriate
4165// implementation
@@ -46,15 +70,34 @@ typedef int void_result_to_python;
4670// converting the result to python.
4771template <class Policies , class Result >
4872struct select_result_converter
49- : mpl::if_ <
73+ : mpl::apply_if <
5074 is_same<Result,void >
51- , void_result_to_python
52- , typename mpl::apply1<typename Policies::result_converter,Result>::type*
75+ , mpl::identity< void_result_to_python>
76+ , mpl::apply1<typename Policies::result_converter,Result>
5377 >
5478{
5579};
5680
57-
81+ template <class ArgPackage , class ResultConverter >
82+ inline ResultConverter create_result_converter (
83+ ArgPackage const & args_
84+ , ResultConverter*
85+ , converter::context_result_converter*
86+ )
87+ {
88+ return ResultConverter (args_);
89+ }
90+
91+ template <class ArgPackage , class ResultConverter >
92+ inline ResultConverter create_result_converter (
93+ ArgPackage const & args_
94+ , ResultConverter*
95+ , ...
96+ )
97+ {
98+ return ResultConverter ();
99+ }
100+
58101template <unsigned > struct caller_arity ;
59102
60103template <class F , class CallPolicies , class Sig >
@@ -63,12 +106,21 @@ struct caller;
63106# define BOOST_PYTHON_NEXT (init,name,n ) \
64107 typedef BOOST_PP_IF (n,typename BOOST_PP_CAT (name,BOOST_PP_DEC(n)) ::next, init) name##n;
65108
109+ # if 0 // argpkg
66110# define BOOST_PYTHON_ARG_CONVERTER (n ) \
67111 BOOST_PYTHON_NEXT (typename first::next, arg_iter,n) \
68112 typedef arg_from_python<BOOST_DEDUCED_TYPENAME arg_iter##n::type> c_t ##n; \
69- c_t ##n c##n(PyTuple_GET_ITEM(args_, n )); \
113+ c_t ##n c##n(get(mpl::int_<n>(), inner_args )); \
70114 if (!c##n.convertible()) \
71115 return 0 ;
116+ # else
117+ # define BOOST_PYTHON_ARG_CONVERTER (n ) \
118+ BOOST_PYTHON_NEXT (typename first::next, arg_iter,n) \
119+ typedef arg_from_python<BOOST_DEDUCED_TYPENAME arg_iter##n::type> c_t ##n; \
120+ c_t ##n c##n(get<n>(inner_args)); \
121+ if (!c##n.convertible()) \
122+ return 0 ;
123+ # endif
72124
73125# define BOOST_PP_ITERATION_PARAMS_1 \
74126 (3 , (0 , BOOST_PYTHON_MAX_ARITY + 1 , <boost/python/detail/caller.hpp>))
@@ -142,24 +194,26 @@ struct caller_arity<N>
142194 typedef typename mpl::begin<Sig>::type first;
143195 typedef typename first::type result_t ;
144196 typedef typename select_result_converter<Policies, result_t >::type result_converter;
197+ typedef typename Policies::argument_package argument_package;
198+
199+ argument_package inner_args (args_);
200+
145201# if N
146202# define BOOST_PP_LOCAL_MACRO (i ) BOOST_PYTHON_ARG_CONVERTER(i)
147203# define BOOST_PP_LOCAL_LIMITS (0 , N-1 )
148204# include BOOST_PP_LOCAL_ITERATE()
149205# endif
150206 // all converters have been checked. Now we can do the
151207 // precall part of the policy
152- PyObject* inner_args = m_data.second ().precall (args_);
153- if (inner_args == 0 )
208+ if (!m_data.second ().precall (inner_args))
154209 return 0 ;
155210
156- // manage the inner arguments
157- handle<> keeper (allow_null (inner_args));
158-
159- typedef typename detail::invoke_tag<F>::type tag;
160-
161211 PyObject* result = detail::invoke (
162- tag (), result_converter (), m_data.first () BOOST_PP_ENUM_TRAILING_PARAMS (N, c));
212+ detail::invoke_tag<result_t ,F>()
213+ , create_result_converter (args_, (result_converter*)0 , (result_converter*)0 )
214+ , m_data.first ()
215+ BOOST_PP_ENUM_TRAILING_PARAMS (N, c)
216+ );
163217
164218 return m_data.second ().postcall (inner_args, result);
165219 }
0 commit comments