sl@0
|
1 |
#if !defined(BOOST_PP_IS_ITERATING)
|
sl@0
|
2 |
|
sl@0
|
3 |
// Copyright David Abrahams 2002.
|
sl@0
|
4 |
// Distributed under the Boost Software License, Version 1.0. (See
|
sl@0
|
5 |
// accompanying file LICENSE_1_0.txt or copy at
|
sl@0
|
6 |
// http://www.boost.org/LICENSE_1_0.txt)
|
sl@0
|
7 |
|
sl@0
|
8 |
# ifndef CALLER_DWA20021121_HPP
|
sl@0
|
9 |
# define CALLER_DWA20021121_HPP
|
sl@0
|
10 |
|
sl@0
|
11 |
# include <boost/python/type_id.hpp>
|
sl@0
|
12 |
# include <boost/python/handle.hpp>
|
sl@0
|
13 |
|
sl@0
|
14 |
# include <boost/python/detail/invoke.hpp>
|
sl@0
|
15 |
# include <boost/python/detail/signature.hpp>
|
sl@0
|
16 |
# include <boost/python/detail/preprocessor.hpp>
|
sl@0
|
17 |
|
sl@0
|
18 |
# include <boost/python/arg_from_python.hpp>
|
sl@0
|
19 |
# include <boost/python/converter/context_result_converter.hpp>
|
sl@0
|
20 |
|
sl@0
|
21 |
# include <boost/preprocessor/iterate.hpp>
|
sl@0
|
22 |
# include <boost/preprocessor/cat.hpp>
|
sl@0
|
23 |
# include <boost/preprocessor/dec.hpp>
|
sl@0
|
24 |
# include <boost/preprocessor/if.hpp>
|
sl@0
|
25 |
# include <boost/preprocessor/iteration/local.hpp>
|
sl@0
|
26 |
# include <boost/preprocessor/repetition/enum_trailing_params.hpp>
|
sl@0
|
27 |
# include <boost/preprocessor/repetition/repeat.hpp>
|
sl@0
|
28 |
|
sl@0
|
29 |
# include <boost/compressed_pair.hpp>
|
sl@0
|
30 |
|
sl@0
|
31 |
# include <boost/type_traits/is_same.hpp>
|
sl@0
|
32 |
# include <boost/type_traits/is_convertible.hpp>
|
sl@0
|
33 |
|
sl@0
|
34 |
# include <boost/mpl/apply.hpp>
|
sl@0
|
35 |
# include <boost/mpl/eval_if.hpp>
|
sl@0
|
36 |
# include <boost/mpl/identity.hpp>
|
sl@0
|
37 |
# include <boost/mpl/size.hpp>
|
sl@0
|
38 |
# include <boost/mpl/at.hpp>
|
sl@0
|
39 |
# include <boost/mpl/int.hpp>
|
sl@0
|
40 |
# include <boost/mpl/next.hpp>
|
sl@0
|
41 |
|
sl@0
|
42 |
namespace boost { namespace python { namespace detail {
|
sl@0
|
43 |
|
sl@0
|
44 |
template <int N>
|
sl@0
|
45 |
inline PyObject* get(mpl::int_<N>, PyObject* const& args_)
|
sl@0
|
46 |
{
|
sl@0
|
47 |
return PyTuple_GET_ITEM(args_,N);
|
sl@0
|
48 |
}
|
sl@0
|
49 |
|
sl@0
|
50 |
inline unsigned arity(PyObject* const& args_)
|
sl@0
|
51 |
{
|
sl@0
|
52 |
return PyTuple_GET_SIZE(args_);
|
sl@0
|
53 |
}
|
sl@0
|
54 |
|
sl@0
|
55 |
// This "result converter" is really just used as
|
sl@0
|
56 |
// a dispatch tag to invoke(...), selecting the appropriate
|
sl@0
|
57 |
// implementation
|
sl@0
|
58 |
typedef int void_result_to_python;
|
sl@0
|
59 |
|
sl@0
|
60 |
// Given a model of CallPolicies and a C++ result type, this
|
sl@0
|
61 |
// metafunction selects the appropriate converter to use for
|
sl@0
|
62 |
// converting the result to python.
|
sl@0
|
63 |
template <class Policies, class Result>
|
sl@0
|
64 |
struct select_result_converter
|
sl@0
|
65 |
: mpl::eval_if<
|
sl@0
|
66 |
is_same<Result,void>
|
sl@0
|
67 |
, mpl::identity<void_result_to_python>
|
sl@0
|
68 |
, mpl::apply1<typename Policies::result_converter,Result>
|
sl@0
|
69 |
>
|
sl@0
|
70 |
{
|
sl@0
|
71 |
};
|
sl@0
|
72 |
|
sl@0
|
73 |
template <class ArgPackage, class ResultConverter>
|
sl@0
|
74 |
inline ResultConverter create_result_converter(
|
sl@0
|
75 |
ArgPackage const& args_
|
sl@0
|
76 |
, ResultConverter*
|
sl@0
|
77 |
, converter::context_result_converter*
|
sl@0
|
78 |
)
|
sl@0
|
79 |
{
|
sl@0
|
80 |
return ResultConverter(args_);
|
sl@0
|
81 |
}
|
sl@0
|
82 |
|
sl@0
|
83 |
template <class ArgPackage, class ResultConverter>
|
sl@0
|
84 |
inline ResultConverter create_result_converter(
|
sl@0
|
85 |
ArgPackage const&
|
sl@0
|
86 |
, ResultConverter*
|
sl@0
|
87 |
, ...
|
sl@0
|
88 |
)
|
sl@0
|
89 |
{
|
sl@0
|
90 |
return ResultConverter();
|
sl@0
|
91 |
}
|
sl@0
|
92 |
|
sl@0
|
93 |
template <unsigned> struct caller_arity;
|
sl@0
|
94 |
|
sl@0
|
95 |
template <class F, class CallPolicies, class Sig>
|
sl@0
|
96 |
struct caller;
|
sl@0
|
97 |
|
sl@0
|
98 |
# define BOOST_PYTHON_NEXT(init,name,n) \
|
sl@0
|
99 |
typedef BOOST_PP_IF(n,typename mpl::next< BOOST_PP_CAT(name,BOOST_PP_DEC(n)) >::type, init) name##n;
|
sl@0
|
100 |
|
sl@0
|
101 |
# define BOOST_PYTHON_ARG_CONVERTER(n) \
|
sl@0
|
102 |
BOOST_PYTHON_NEXT(typename mpl::next<first>::type, arg_iter,n) \
|
sl@0
|
103 |
typedef arg_from_python<BOOST_DEDUCED_TYPENAME arg_iter##n::type> c_t##n; \
|
sl@0
|
104 |
c_t##n c##n(get(mpl::int_<n>(), inner_args)); \
|
sl@0
|
105 |
if (!c##n.convertible()) \
|
sl@0
|
106 |
return 0;
|
sl@0
|
107 |
|
sl@0
|
108 |
# define BOOST_PP_ITERATION_PARAMS_1 \
|
sl@0
|
109 |
(3, (0, BOOST_PYTHON_MAX_ARITY + 1, <boost/python/detail/caller.hpp>))
|
sl@0
|
110 |
# include BOOST_PP_ITERATE()
|
sl@0
|
111 |
|
sl@0
|
112 |
# undef BOOST_PYTHON_ARG_CONVERTER
|
sl@0
|
113 |
# undef BOOST_PYTHON_NEXT
|
sl@0
|
114 |
|
sl@0
|
115 |
// A metafunction returning the base class used for caller<class F,
|
sl@0
|
116 |
// class ConverterGenerators, class CallPolicies, class Sig>.
|
sl@0
|
117 |
template <class F, class CallPolicies, class Sig>
|
sl@0
|
118 |
struct caller_base_select
|
sl@0
|
119 |
{
|
sl@0
|
120 |
enum { arity = mpl::size<Sig>::value - 1 };
|
sl@0
|
121 |
typedef typename caller_arity<arity>::template impl<F,CallPolicies,Sig> type;
|
sl@0
|
122 |
};
|
sl@0
|
123 |
|
sl@0
|
124 |
// A function object type which wraps C++ objects as Python callable
|
sl@0
|
125 |
// objects.
|
sl@0
|
126 |
//
|
sl@0
|
127 |
// Template Arguments:
|
sl@0
|
128 |
//
|
sl@0
|
129 |
// F -
|
sl@0
|
130 |
// the C++ `function object' that will be called. Might
|
sl@0
|
131 |
// actually be any data for which an appropriate invoke_tag() can
|
sl@0
|
132 |
// be generated. invoke(...) takes care of the actual invocation syntax.
|
sl@0
|
133 |
//
|
sl@0
|
134 |
// CallPolicies -
|
sl@0
|
135 |
// The precall, postcall, and what kind of resultconverter to
|
sl@0
|
136 |
// generate for mpl::front<Sig>::type
|
sl@0
|
137 |
//
|
sl@0
|
138 |
// Sig -
|
sl@0
|
139 |
// The `intended signature' of the function. An MPL sequence
|
sl@0
|
140 |
// beginning with a result type and continuing with a list of
|
sl@0
|
141 |
// argument types.
|
sl@0
|
142 |
template <class F, class CallPolicies, class Sig>
|
sl@0
|
143 |
struct caller
|
sl@0
|
144 |
: caller_base_select<F,CallPolicies,Sig>::type
|
sl@0
|
145 |
{
|
sl@0
|
146 |
typedef typename caller_base_select<
|
sl@0
|
147 |
F,CallPolicies,Sig
|
sl@0
|
148 |
>::type base;
|
sl@0
|
149 |
|
sl@0
|
150 |
typedef PyObject* result_type;
|
sl@0
|
151 |
|
sl@0
|
152 |
caller(F f, CallPolicies p) : base(f,p) {}
|
sl@0
|
153 |
|
sl@0
|
154 |
};
|
sl@0
|
155 |
|
sl@0
|
156 |
}}} // namespace boost::python::detail
|
sl@0
|
157 |
|
sl@0
|
158 |
# endif // CALLER_DWA20021121_HPP
|
sl@0
|
159 |
|
sl@0
|
160 |
#else
|
sl@0
|
161 |
|
sl@0
|
162 |
# define N BOOST_PP_ITERATION()
|
sl@0
|
163 |
|
sl@0
|
164 |
template <>
|
sl@0
|
165 |
struct caller_arity<N>
|
sl@0
|
166 |
{
|
sl@0
|
167 |
template <class F, class Policies, class Sig>
|
sl@0
|
168 |
struct impl
|
sl@0
|
169 |
{
|
sl@0
|
170 |
impl(F f, Policies p) : m_data(f,p) {}
|
sl@0
|
171 |
|
sl@0
|
172 |
PyObject* operator()(PyObject* args_, PyObject*) // eliminate
|
sl@0
|
173 |
// this
|
sl@0
|
174 |
// trailing
|
sl@0
|
175 |
// keyword dict
|
sl@0
|
176 |
{
|
sl@0
|
177 |
typedef typename mpl::begin<Sig>::type first;
|
sl@0
|
178 |
typedef typename first::type result_t;
|
sl@0
|
179 |
typedef typename select_result_converter<Policies, result_t>::type result_converter;
|
sl@0
|
180 |
typedef typename Policies::argument_package argument_package;
|
sl@0
|
181 |
|
sl@0
|
182 |
argument_package inner_args(args_);
|
sl@0
|
183 |
|
sl@0
|
184 |
# if N
|
sl@0
|
185 |
# define BOOST_PP_LOCAL_MACRO(i) BOOST_PYTHON_ARG_CONVERTER(i)
|
sl@0
|
186 |
# define BOOST_PP_LOCAL_LIMITS (0, N-1)
|
sl@0
|
187 |
# include BOOST_PP_LOCAL_ITERATE()
|
sl@0
|
188 |
# endif
|
sl@0
|
189 |
// all converters have been checked. Now we can do the
|
sl@0
|
190 |
// precall part of the policy
|
sl@0
|
191 |
if (!m_data.second().precall(inner_args))
|
sl@0
|
192 |
return 0;
|
sl@0
|
193 |
|
sl@0
|
194 |
PyObject* result = detail::invoke(
|
sl@0
|
195 |
detail::invoke_tag<result_t,F>()
|
sl@0
|
196 |
, create_result_converter(args_, (result_converter*)0, (result_converter*)0)
|
sl@0
|
197 |
, m_data.first()
|
sl@0
|
198 |
BOOST_PP_ENUM_TRAILING_PARAMS(N, c)
|
sl@0
|
199 |
);
|
sl@0
|
200 |
|
sl@0
|
201 |
return m_data.second().postcall(inner_args, result);
|
sl@0
|
202 |
}
|
sl@0
|
203 |
|
sl@0
|
204 |
static unsigned min_arity() { return N; }
|
sl@0
|
205 |
|
sl@0
|
206 |
static signature_element const* signature()
|
sl@0
|
207 |
{
|
sl@0
|
208 |
return detail::signature<Sig>::elements();
|
sl@0
|
209 |
}
|
sl@0
|
210 |
|
sl@0
|
211 |
private:
|
sl@0
|
212 |
compressed_pair<F,Policies> m_data;
|
sl@0
|
213 |
};
|
sl@0
|
214 |
};
|
sl@0
|
215 |
|
sl@0
|
216 |
|
sl@0
|
217 |
|
sl@0
|
218 |
#endif // BOOST_PP_IS_ITERATING
|
sl@0
|
219 |
|
sl@0
|
220 |
|