Skip to content

Commit bec2de0

Browse files
committed
Use make_function uniformly to build callable objects.
Fix wstring support so it doesn't break gcc2.95.x, which has no wstring. Modify CallPolicies protocol so it can safely adjust the argument tuple. [SVN r20090]
1 parent db192e1 commit bec2de0

File tree

14 files changed

+288
-304
lines changed

14 files changed

+288
-304
lines changed

include/boost/python/converter/builtin_converters.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,9 @@ BOOST_PYTHON_TO_PYTHON_BY_VALUE(unsigned BOOST_PYTHON_LONG_LONG, ::PyLong_FromUn
112112
BOOST_PYTHON_TO_PYTHON_BY_VALUE(char, converter::do_return_to_python(x))
113113
BOOST_PYTHON_TO_PYTHON_BY_VALUE(char const*, converter::do_return_to_python(x))
114114
BOOST_PYTHON_TO_PYTHON_BY_VALUE(std::string, ::PyString_FromStringAndSize(x.data(),x.size()))
115+
# ifndef BOOST_NO_STD_WSTRING
115116
BOOST_PYTHON_TO_PYTHON_BY_VALUE(std::wstring, ::PyUnicode_FromWideChar(x.data(),x.size()))
117+
# endif
116118
BOOST_PYTHON_TO_PYTHON_BY_VALUE(float, ::PyFloat_FromDouble(x))
117119
BOOST_PYTHON_TO_PYTHON_BY_VALUE(double, ::PyFloat_FromDouble(x))
118120
BOOST_PYTHON_TO_PYTHON_BY_VALUE(long double, ::PyFloat_FromDouble(x))

include/boost/python/data_members.hpp

Lines changed: 60 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,12 @@
88

99
# include <boost/python/detail/prefix.hpp>
1010

11+
# include <boost/python/handle.hpp>
12+
1113
# include <boost/python/return_value_policy.hpp>
1214
# include <boost/python/return_by_value.hpp>
1315
# include <boost/python/return_internal_reference.hpp>
14-
# include <boost/python/arg_from_python.hpp>
15-
16-
# include <boost/python/object/function_object.hpp>
16+
# include <boost/python/make_function.hpp>
1717

1818
# include <boost/python/converter/builtin_converters.hpp>
1919

@@ -24,12 +24,14 @@
2424
# include <boost/type_traits/add_reference.hpp>
2525
# include <boost/type_traits/is_member_pointer.hpp>
2626

27+
# if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003))
28+
# include <boost/type_traits/remove_cv.hpp>
29+
# endif
30+
2731
# include <boost/mpl/apply_if.hpp>
2832
# include <boost/mpl/if.hpp>
2933
# include <boost/mpl/vector/vector10.hpp>
3034

31-
# include <boost/bind.hpp>
32-
3335
# include <boost/detail/workaround.hpp>
3436

3537
namespace boost { namespace python {
@@ -43,97 +45,57 @@ namespace boost { namespace python {
4345

4446
namespace detail
4547
{
46-
//
47-
// Raw Getter and Setter function generators. These class templates
48-
// generate static functions which can be bound together with
49-
// policies and wrapped to generate the python callable objects
50-
// mentioned above.
51-
//
5248

53-
//
54-
// Generates get and set functions for access through
55-
// pointers-to-data-members
56-
//
57-
template <class Data, class Class, class Policies>
49+
// A small function object which handles the getting and setting of
50+
// data members.
51+
template <class Data, class Class>
5852
struct member
5953
{
60-
static PyObject* get(Data Class::*pm, PyObject* args_, PyObject*, Policies const& policies)
54+
private:
55+
typedef typename add_const<Data>::type data_const;
56+
typedef typename add_reference<data_const>::type data_cref;
57+
58+
public:
59+
member(Data Class::*which) : m_which(which) {}
60+
61+
Data& operator()(Class& c) const
6162
{
62-
arg_from_python<Class*> c0(PyTuple_GET_ITEM(args_, 0));
63-
if (!c0.convertible()) return 0;
64-
65-
// find the result converter
66-
typedef typename Policies::result_converter result_converter;
67-
typedef typename boost::add_reference<Data>::type source;
68-
typename mpl::apply1<result_converter,source>::type cr;
69-
70-
if (!policies.precall(args_)) return 0;
71-
72-
PyObject* result = cr( (c0())->*pm );
73-
74-
return policies.postcall(args_, result);
63+
return c.*m_which;
7564
}
76-
77-
static PyObject* set(Data Class::*pm, PyObject* args_, PyObject*, Policies const& policies)
78-
{
79-
// check that each of the arguments is convertible
80-
arg_from_python<Class&> c0(PyTuple_GET_ITEM(args_, 0));
81-
if (!c0.convertible()) return 0;
82-
83-
typedef typename add_const<Data>::type target1;
84-
typedef typename add_reference<target1>::type target;
85-
arg_from_python<target> c1(PyTuple_GET_ITEM(args_, 1));
86-
87-
if (!c1.convertible()) return 0;
8865

89-
if (!policies.precall(args_)) return 0;
90-
91-
(c0()).*pm = c1();
92-
93-
return policies.postcall(args_, detail::none());
66+
void operator()(Class& c, data_cref d) const
67+
{
68+
c.*m_which = d;
9469
}
70+
private:
71+
Data Class::*m_which;
9572
};
9673

97-
//
98-
// Generates get and set functions for access through ordinary
99-
// pointers. These are generally used to wrap static data members,
100-
// but can also be used to expose namespace-scope data as class
101-
// attributes.
102-
//
103-
template <class Data, class Policies>
74+
// A small function object which handles the getting and setting of
75+
// non-member objects.
76+
template <class Data>
10477
struct datum
10578
{
106-
static PyObject* get(Data *p, PyObject* args_, PyObject*, Policies const& policies)
79+
private:
80+
typedef typename add_const<Data>::type data_const;
81+
typedef typename add_reference<data_const>::type data_cref;
82+
83+
public:
84+
datum(Data *which) : m_which(which) {}
85+
86+
Data& operator()() const
10787
{
108-
// find the result converter
109-
typedef typename Policies::result_converter result_converter;
110-
typedef typename boost::add_reference<Data>::type source;
111-
typename mpl::apply1<result_converter,source>::type cr;
112-
113-
if (!policies.precall(args_)) return 0;
114-
115-
PyObject* result = cr( *p );
116-
117-
return policies.postcall(args_, result);
88+
return *m_which;
11889
}
119-
120-
static PyObject* set(Data* p, PyObject* args_, PyObject*, Policies const& policies)
121-
{
122-
// check that each of the arguments is convertible
123-
typedef typename add_const<Data>::type target1;
124-
typedef typename add_reference<target1>::type target;
125-
arg_from_python<target> c0(PyTuple_GET_ITEM(args_, 0));
126-
127-
if (!c0.convertible()) return 0;
12890

129-
if (!policies.precall(args_)) return 0;
130-
131-
*p = c0();
132-
133-
return policies.postcall(args_, detail::none());
91+
void operator()(data_cref d) const
92+
{
93+
*m_which = d;
13494
}
95+
private:
96+
Data *m_which;
13597
};
136-
98+
13799
//
138100
// Helper metafunction for determining the default CallPolicy to use
139101
// for attribute access. If T is a [reference to a] class type X
@@ -208,13 +170,8 @@ namespace detail
208170
template <class D, class Policies>
209171
inline object make_getter(D* d, Policies const& policies, mpl::false_, int)
210172
{
211-
return objects::function_object(
212-
objects::py_function(
213-
::boost::bind(
214-
&detail::datum<D,Policies>::get, d, _1, _2
215-
, policies)
216-
, mpl::vector1<D>()
217-
)
173+
return python::make_function(
174+
detail::datum<D>(d), policies, mpl::vector1<D&>()
218175
);
219176
}
220177

@@ -230,14 +187,16 @@ namespace detail
230187
template <class C, class D, class Policies>
231188
inline object make_getter(D C::*pm, Policies const& policies, mpl::true_, int)
232189
{
233-
return objects::function_object(
234-
objects::py_function(
235-
::boost::bind(
236-
&detail::member<D,C,Policies>::get, pm, _1, _2
237-
, policies)
238-
, mpl::vector2<D, C const*>()
239-
)
240-
);
190+
#if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003))
191+
typedef typename remove_cv<C>::type Class;
192+
#else
193+
typedef C Class;
194+
#endif
195+
return python::make_function(
196+
detail::member<D,Class>(pm)
197+
, policies
198+
, mpl::vector2<D&,Class&>()
199+
);
241200
}
242201

243202
// Handle pointers-to-members without policies
@@ -268,27 +227,19 @@ namespace detail
268227
template <class D, class Policies>
269228
inline object make_setter(D* p, Policies const& policies, mpl::false_, int)
270229
{
271-
return objects::function_object(
272-
objects::py_function(
273-
::boost::bind(
274-
&detail::datum<D,Policies>::set, p, _1, _2
275-
, policies)
276-
, mpl::vector2<void, D const&>()
277-
)
230+
return python::make_function(
231+
detail::datum<D>(p), policies, mpl::vector2<void,D const&>()
278232
);
279233
}
280234

281235
// Handle pointers-to-members
282236
template <class C, class D, class Policies>
283237
inline object make_setter(D C::*pm, Policies const& policies, mpl::true_, int)
284238
{
285-
return objects::function_object(
286-
objects::py_function(
287-
::boost::bind(
288-
&detail::member<D,C,Policies>::set, pm, _1, _2
289-
, policies)
290-
, mpl::vector3<void, C*, D const&>()
291-
)
239+
return python::make_function(
240+
detail::member<D,C>(pm)
241+
, policies
242+
, mpl::vector3<void, C&, D const&>()
292243
);
293244
}
294245

include/boost/python/default_call_policies.hpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,16 @@ struct default_result_converter;
2929

3030
struct default_call_policies
3131
{
32-
// Nothing to do
33-
static bool precall(PyObject*)
32+
// Ownership of this argument tuple will ultimately be adopted by
33+
// the caller.
34+
static PyObject* precall(PyObject* args_)
3435
{
35-
return true;
36+
Py_INCREF(args_);
37+
return args_;
3638
}
3739

3840
// Pass the result through
39-
static PyObject* postcall(PyObject*, PyObject* result)
41+
static PyObject* postcall(PyObject* args_, PyObject* result)
4042
{
4143
return result;
4244
}

include/boost/python/detail/caller.hpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
# include <boost/type_traits/is_same.hpp>
1919

2020
# include <boost/python/type_id.hpp>
21+
# include <boost/python/handle.hpp>
22+
2123
# include <boost/python/detail/invoke.hpp>
2224
# include <boost/python/detail/signature.hpp>
2325
# include <boost/python/detail/preprocessor.hpp>
@@ -147,15 +149,19 @@ struct caller_arity<N>
147149
# endif
148150
// all converters have been checked. Now we can do the
149151
// precall part of the policy
150-
if (!m_data.second().precall(args_))
152+
PyObject* inner_args = m_data.second().precall(args_);
153+
if (inner_args == 0)
151154
return 0;
152155

156+
// manage the inner arguments
157+
handle<> keeper(allow_null(inner_args));
158+
153159
typedef typename detail::invoke_tag<F>::type tag;
154160

155161
PyObject* result = detail::invoke(
156162
tag(), result_converter(), m_data.first() BOOST_PP_ENUM_TRAILING_PARAMS(N, c));
157163

158-
return m_data.second().postcall(args_, result);
164+
return m_data.second().postcall(inner_args, result);
159165
}
160166

161167
static unsigned min_arity() { return N; }

include/boost/python/detail/target.hpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ namespace boost { namespace python { namespace detail {
3131
# include BOOST_PP_ITERATE()
3232

3333
template <class R, class T>
34-
boost::type<T*>* target(R (T::*)) { return 0; }
34+
T& (* target(R (T::*)) )() { return 0; }
3535

3636
}}} // namespace boost::python::detail
3737

@@ -44,7 +44,7 @@ boost::type<T*>* target(R (T::*)) { return 0; }
4444
# define N BOOST_PP_ITERATION()
4545

4646
template <class R BOOST_PP_ENUM_TRAILING_PARAMS_Z(1, N, class A)>
47-
boost::type<BOOST_PP_IF(N, A0, void)>* target(R (*)(BOOST_PP_ENUM_PARAMS_Z(1, N, A)))
47+
BOOST_PP_IF(N, A0, void)(* target(R (*)(BOOST_PP_ENUM_PARAMS_Z(1, N, A))) )()
4848
{
4949
return 0;
5050
}
@@ -66,7 +66,7 @@ boost::type<BOOST_PP_IF(N, A0, void)>* target(R (*)(BOOST_PP_ENUM_PARAMS_Z(1, N,
6666
# define Q BOOST_PYTHON_CV_QUALIFIER(BOOST_PP_RELATIVE_ITERATION(1))
6767

6868
template <class R, class T BOOST_PP_ENUM_TRAILING_PARAMS_Z(1, N, class A)>
69-
boost::type<T Q*>* target(R (T::*)(BOOST_PP_ENUM_PARAMS_Z(1, N, A)) Q)
69+
T& (* target(R (T::*)(BOOST_PP_ENUM_PARAMS_Z(1, N, A)) Q) )()
7070
{
7171
return 0;
7272
}

include/boost/python/init.hpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -393,13 +393,13 @@ namespace detail
393393
template <class ClassT, class CallPoliciesT, class Signature, class NArgs>
394394
static void apply(
395395
ClassT& cl
396-
, CallPoliciesT const& policies
397-
, Signature const& args
398-
, NArgs
399-
, char const* doc
400-
, detail::keyword_range const& keywords)
396+
, CallPoliciesT const& policies
397+
, Signature const& args
398+
, NArgs
399+
, char const* doc
400+
, detail::keyword_range const& keywords)
401401
{
402-
def_init_aux(cl, args, NArgs(), policies, doc, keywords);
402+
detail::def_init_aux(cl, args, NArgs(), policies, doc, keywords);
403403
}
404404
};
405405
}

0 commit comments

Comments
 (0)