Skip to content

Commit e14e4e1

Browse files
committed
New function invocation mechanism. This is the major groundwork for handling virtual functions with default implementations properly
[SVN r16388]
1 parent 05ce65d commit e14e4e1

File tree

13 files changed

+557
-183
lines changed

13 files changed

+557
-183
lines changed

include/boost/python/class.hpp

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -107,12 +107,8 @@ namespace detail
107107
};
108108
}
109109

110-
//
111-
// class_<T,Bases,HolderGenerator>
112-
//
113-
// This is the primary mechanism through which users will expose
114-
// C++ classes to Python. The three template arguments are:
115-
//
110+
// This is the primary mechanism through which users will expose
111+
// C++ classes to Python.
116112
template <
117113
class T // class being wrapped
118114
, class X1 // = detail::not_specified

include/boost/python/converter/registrations.hpp

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,15 @@ struct rvalue_from_python_chain
2727
rvalue_from_python_chain* next;
2828
};
2929

30-
struct registration
30+
struct BOOST_PYTHON_DECL registration
3131
{
32+
public: // member functions
3233
explicit registration(type_info);
3334

35+
// Convert the appropriately-typed data to Python
36+
PyObject* to_python(void const volatile*) const;
37+
38+
public: // data members. So sue me.
3439
const python::type_info target_type;
3540

3641
// The chain of eligible from_python converters when an lvalue is required
@@ -39,11 +44,11 @@ struct registration
3944
// The chain of eligible from_python converters when an rvalue is acceptable
4045
rvalue_from_python_chain* rvalue_chain;
4146

42-
// The unique to_python converter for the associated C++ type.
43-
to_python_function_t to_python;
44-
4547
// The class object associated with this type
4648
PyTypeObject* class_object;
49+
50+
// The unique to_python converter for the associated C++ type.
51+
to_python_function_t m_to_python;
4752
};
4853

4954
//
@@ -53,7 +58,7 @@ inline registration::registration(type_info target_type)
5358
: target_type(target_type)
5459
, lvalue_chain(0)
5560
, rvalue_chain(0)
56-
, to_python(0)
61+
, m_to_python(0)
5762
, class_object(0)
5863
{}
5964

include/boost/python/detail/arg_tuple_size.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
#error obsolete
12
#if !defined(BOOST_PP_IS_ITERATING)
23

34
// (C) Copyright David Abrahams 2001. Permission to copy, use, modify, sell and

include/boost/python/detail/caller.hpp

Lines changed: 146 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -1,106 +1,175 @@
11
#if !defined(BOOST_PP_IS_ITERATING)
22

3-
// (C) Copyright David Abrahams 2000. Permission to copy, use, modify, sell and
4-
// distribute this software is granted provided this copyright notice appears
5-
// in all copies. This software is provided "as is" without express or implied
6-
// warranty, and with no claim as to its suitability for any purpose.
7-
//
8-
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
9-
// producing this work.
10-
//
11-
// This file generated for 10-argument member functions and 11-argument free
12-
// functions by gen_caller.python
3+
// Copyright David Abrahams 2002. Permission to copy, use,
4+
// modify, sell and distribute this software is granted provided this
5+
// copyright notice appears in all copies. This software is provided
6+
// "as is" without express or implied warranty, and with no claim as
7+
// to its suitability for any purpose.
138

14-
# ifndef CALLER_DWA20011214_HPP
15-
# define CALLER_DWA20011214_HPP
9+
# ifndef CALLER_DWA20021121_HPP
10+
# define CALLER_DWA20021121_HPP
1611

17-
# include <boost/python/detail/wrap_python.hpp>
18-
# include <boost/python/detail/returning.hpp>
19-
# include <boost/python/detail/preprocessor.hpp>
12+
# include <boost/compressed_pair.hpp>
2013

21-
# include <boost/type_traits/composite_traits.hpp>
22-
# include <boost/type_traits/same_traits.hpp>
14+
# include <boost/mpl/apply.hpp>
15+
# include <boost/mpl/if.hpp>
16+
# include <boost/mpl/size.hpp>
17+
# include <boost/type_traits/is_same.hpp>
2318

24-
# include <boost/preprocessor/comma_if.hpp>
19+
# include <boost/python/detail/preprocessor.hpp>
2520
# include <boost/preprocessor/iterate.hpp>
26-
# include <boost/preprocessor/debug/line.hpp>
21+
# include <boost/preprocessor/iteration/local.hpp>
2722
# include <boost/preprocessor/repetition/enum_trailing_params.hpp>
28-
29-
namespace boost { namespace python
23+
# include <boost/preprocessor/repetition/repeat.hpp>
24+
# include <boost/preprocessor/cat.hpp>
25+
# include <boost/preprocessor/dec.hpp>
26+
# include <boost/preprocessor/if.hpp>
27+
28+
# include <boost/python/detail/invoke.hpp>
29+
30+
namespace boost { namespace python { namespace detail {
31+
32+
// This "result converter" is really just used as
33+
// a dispatch tag to invoke(...), selecting the appropriate
34+
// implementation
35+
typedef int void_result_to_python;
36+
37+
// A metafunction taking an iterator FunctionIter to a metafunction
38+
// class and an iterator ArgIter to an argument, which applies the
39+
// result of dereferencing FunctionIter to the result of dereferencing
40+
// ArgIter
41+
template <class FunctionIter, class ArgIter>
42+
struct apply_iter1
43+
: mpl::apply1<typename FunctionIter::type, typename ArgIter::type> {};
44+
45+
// Given a model of CallPolicies and a C++ result type, this
46+
// metafunction selects the appropriate converter to use for
47+
// converting the result to python.
48+
template <class Policies, class Result>
49+
struct select_result_converter
50+
: mpl::if_<
51+
is_same<Result,void>
52+
, void_result_to_python
53+
, typename mpl::apply1<typename Policies::result_converter,Result>::type*
54+
>
3055
{
31-
template <class T> struct to_python;
32-
}}
56+
};
3357

34-
namespace boost { namespace python { namespace detail {
3558

36-
struct caller
37-
{
38-
typedef PyObject* result_type;
59+
template <unsigned> struct caller_gen;
3960

40-
// function pointers
41-
# define BOOST_PP_ITERATION_PARAMS_1 \
42-
(4, (0, BOOST_PYTHON_MAX_ARITY, <boost/python/detail/caller.hpp>, BOOST_PYTHON_FUNCTION_POINTER))
43-
# include BOOST_PP_ITERATE()
61+
# define BOOST_PYTHON_NEXT(init,name,n) \
62+
typedef BOOST_PP_IF(n,typename BOOST_PP_CAT(name,BOOST_PP_DEC(n)) ::next, init) name##n;
4463

45-
// pointers-to-members
46-
# define BOOST_PP_ITERATION_PARAMS_1 \
47-
(4, (0, 3, <boost/python/detail/caller.hpp>, BOOST_PYTHON_POINTER_TO_MEMBER))
64+
# define BOOST_PYTHON_ARG_CONVERTER(n) \
65+
BOOST_PYTHON_NEXT(typename first::next, arg_iter,n) \
66+
BOOST_PYTHON_NEXT(ConverterGenerators, conv_iter,n) \
67+
typedef typename apply_iter1<conv_iter##n,arg_iter##n>::type c_t##n; \
68+
c_t##n c##n(PyTuple_GET_ITEM(args_, n)); \
69+
if (!c##n.convertible()) \
70+
return 0;
71+
72+
# define BOOST_PP_ITERATION_PARAMS_1 \
73+
(3, (0, BOOST_PYTHON_MAX_ARITY + 1, <boost/python/detail/caller.hpp>))
4874
# include BOOST_PP_ITERATE()
4975

76+
# undef BOOST_PYTHON_ARG_CONVERTER
77+
# undef BOOST_PYTHON_NEXT
78+
79+
// A metafunction returning the base class used for caller<class F,
80+
// class ConverterGenerators, class CallPolicies, class Sig>.
81+
template <class F, class ConverterGenerators, class CallPolicies, class Sig>
82+
struct caller_base_select
83+
{
84+
enum { n_arguments = mpl::size<Sig>::value - 1 };
85+
typedef typename caller_gen<n_arguments>::template impl<F,ConverterGenerators,CallPolicies,Sig> type;
5086
};
5187

52-
}}} // namespace boost::python::detail
88+
// A function object type which wraps C++ objects as Python callable
89+
// objects.
90+
//
91+
// Template Arguments:
92+
//
93+
// F -
94+
// the C++ `function object' that will be called. Might
95+
// actually be any data for which an appropriate invoke_tag() can
96+
// be generated. invoke(...) takes care of the actual invocation syntax.
97+
//
98+
// ConverterGenerators -
99+
// An MPL iterator type over a sequence of metafunction classes
100+
// that can be applied to element 1...N of Sig to produce
101+
// argument from_python converters for the arguments
102+
//
103+
// CallPolicies -
104+
// The precall, postcall, and what kind of resultconverter to
105+
// generate for mpl::front<Sig>::type
106+
//
107+
// Sig -
108+
// The `intended signature' of the function. An MPL sequence
109+
// beginning with a result type and continuing with a list of
110+
// argument types.
111+
template <class F, class ConverterGenerators, class CallPolicies, class Sig>
112+
struct caller
113+
: caller_base_select<F,ConverterGenerators,CallPolicies,Sig>::type
114+
{
115+
typedef typename caller_base_select<
116+
F,ConverterGenerators,CallPolicies,Sig
117+
>::type base;
53118

54-
# endif // CALLER_DWA20011214_HPP
119+
typedef PyObject* result_type;
120+
121+
caller(F f, CallPolicies p) : base(f,p) {}
122+
};
55123

56-
/* ---------- function pointers --------- */
57-
#elif BOOST_PP_ITERATION_DEPTH() == 1 && BOOST_PP_ITERATION_FLAGS() == BOOST_PYTHON_FUNCTION_POINTER
58-
# line BOOST_PP_LINE(__LINE__, detail/caller.hpp(function pointers))
59124

60-
# define N BOOST_PP_ITERATION()
125+
}}} // namespace boost::python::detail
61126

62-
template <
63-
class P, class R
64-
BOOST_PP_ENUM_TRAILING_PARAMS_Z(1, N, class A)
65-
>
66-
PyObject* operator()(
67-
R (*pf)(BOOST_PP_ENUM_PARAMS_Z(1, N, A))
68-
, PyObject* args
69-
, PyObject* keywords
70-
, P const& policies) const
71-
{
72-
return returning<R>::call(pf, args, keywords, &policies);
73-
}
127+
# endif // CALLER_DWA20021121_HPP
74128

75-
# undef N
129+
#else
76130

77-
/* ---------- pointers-to-members ---------- */
78-
#elif BOOST_PP_ITERATION_DEPTH() == 1 && BOOST_PP_ITERATION_FLAGS() == BOOST_PYTHON_POINTER_TO_MEMBER
79-
// outer over cv-qualifiers
131+
# define N BOOST_PP_ITERATION()
80132

81-
# define BOOST_PP_ITERATION_PARAMS_2 (3, (0, BOOST_PYTHON_MAX_ARITY, <boost/python/detail/caller.hpp>))
82-
# include BOOST_PP_ITERATE()
133+
template <>
134+
struct caller_gen<N>
135+
{
136+
template <class F, class ConverterGenerators, class Policies, class Sig>
137+
struct impl
138+
{
139+
impl(F f, Policies p) : m_data(f,p) {}
140+
141+
PyObject* operator()(PyObject* args_, PyObject*) // eliminate
142+
// this
143+
// trailing
144+
// keyword dict
145+
{
146+
typedef typename mpl::begin<Sig>::type first;
147+
typedef typename first::type result_t;
148+
typedef typename select_result_converter<Policies, result_t>::type result_converter;
149+
# if N
150+
# define BOOST_PP_LOCAL_MACRO(i) BOOST_PYTHON_ARG_CONVERTER(i)
151+
# define BOOST_PP_LOCAL_LIMITS (0, N-1)
152+
# include BOOST_PP_LOCAL_ITERATE()
153+
# endif
154+
// all converters have been checked. Now we can do the
155+
// precall part of the policy
156+
if (!m_data.second().precall(args_))
157+
return 0;
158+
159+
typedef typename detail::invoke_tag<F>::type tag;
160+
161+
PyObject* result = detail::invoke(
162+
tag(), result_converter(), m_data.first() BOOST_PP_ENUM_TRAILING_PARAMS(N, c));
163+
164+
return m_data.second().postcall(args_, result);
165+
}
166+
private:
167+
compressed_pair<F,Policies> m_data;
168+
};
169+
};
83170

84-
#elif BOOST_PP_ITERATION_DEPTH() == 2
85-
// inner over arities
86171

87-
#define N BOOST_PP_ITERATION()
88-
#define Q BOOST_PYTHON_CV_QUALIFIER(BOOST_PP_RELATIVE_ITERATION(1))
89172

90-
template <
91-
class P, class R, class T
92-
BOOST_PP_ENUM_TRAILING_PARAMS_Z(1, N, class A)
93-
>
94-
PyObject* operator()(
95-
R (T::*pmf)(BOOST_PP_ENUM_PARAMS_Z(1, N, A)) Q
96-
, PyObject* args, PyObject* keywords
97-
, P const& policies
98-
) const
99-
{
100-
return returning<R>::call(pmf, args, keywords, &policies);
101-
}
173+
#endif // BOOST_PP_IS_ITERATING
102174

103-
#undef N
104-
#undef Q
105175

106-
#endif

0 commit comments

Comments
 (0)