Skip to content

Commit 3fd9ad7

Browse files
committed
implement static data members
[SVN r18157]
1 parent 319a5cf commit 3fd9ad7

File tree

5 files changed

+564
-73
lines changed

5 files changed

+564
-73
lines changed

include/boost/python/class.hpp

Lines changed: 72 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -290,19 +290,28 @@ class class_ : public objects::class_base
290290
//
291291
// Data member access
292292
//
293-
template <class D, class B>
294-
self& def_readonly(char const* name, D B::*pm_)
293+
template <class D>
294+
self& def_readonly(char const* name, D const& d)
295295
{
296-
D T::*pm = pm_;
297-
this->add_property(name, make_getter(pm));
298-
return *this;
296+
return this->def_readonly_impl(name, d, 0);
299297
}
300298

301-
template <class D, class B>
302-
self& def_readwrite(char const* name, D B::*pm_)
299+
template <class D>
300+
self& def_readwrite(char const* name, D const& d)
303301
{
304-
D T::*pm = pm_;
305-
return this->add_property(name, make_getter(pm), make_setter(pm));
302+
return this->def_readwrite_impl(name, d, 0);
303+
}
304+
305+
template <class D>
306+
self& def_readonly(char const* name, D& d)
307+
{
308+
return this->def_readonly_impl(name, d, 0);
309+
}
310+
311+
template <class D>
312+
self& def_readwrite(char const* name, D& d)
313+
{
314+
return this->def_readwrite_impl(name, d, 0);
306315
}
307316

308317
// Property creation
@@ -334,6 +343,34 @@ class class_ : public objects::class_base
334343
return *this;
335344
}
336345

346+
template <class Get>
347+
self& add_static_property(char const* name, Get fget)
348+
{
349+
base::add_static_property(
350+
name
351+
, object(
352+
detail::member_function_cast<T,Get>::stage1(fget).stage2((T*)0).stage3(fget)
353+
)
354+
);
355+
356+
return *this;
357+
}
358+
359+
template <class Get, class Set>
360+
self& add_static_property(char const* name, Get fget, Set fset)
361+
{
362+
base::add_static_property(
363+
name
364+
, object(
365+
detail::member_function_cast<T,Get>::stage1(fget).stage2((T*)0).stage3(fget)
366+
)
367+
, object(
368+
detail::member_function_cast<T,Set>::stage1(fset).stage2((T*)0).stage3(fset)
369+
)
370+
);
371+
return *this;
372+
}
373+
337374
template <class U>
338375
self& setattr(char const* name, U const& x)
339376
{
@@ -362,6 +399,32 @@ class class_ : public objects::class_base
362399
}
363400
private: // helper functions
364401

402+
template <class D, class B>
403+
self& def_readonly_impl(char const* name, D B::*pm_, int)
404+
{
405+
D T::*pm = pm_;
406+
return this->add_property(name, make_getter(pm));
407+
}
408+
409+
template <class D, class B>
410+
self& def_readwrite_impl(char const* name, D B::*pm_, int)
411+
{
412+
D T::*pm = pm_;
413+
return this->add_property(name, make_getter(pm), make_setter(pm));
414+
}
415+
416+
template <class D>
417+
self& def_readonly_impl(char const* name, D& d, ...)
418+
{
419+
return this->add_static_property(name, make_getter(d));
420+
}
421+
422+
template <class D>
423+
self& def_readwrite_impl(char const* name, D& d, ...)
424+
{
425+
return this->add_static_property(name, make_getter(d), make_setter(d));
426+
}
427+
365428
inline void register_() const;
366429

367430
//

include/boost/python/data_members.hpp

Lines changed: 146 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,16 @@
1818
# include <boost/python/detail/indirect_traits.hpp>
1919
# include <boost/python/detail/config.hpp>
2020
# include <boost/python/detail/wrap_python.hpp>
21+
# include <boost/python/detail/not_specified.hpp>
2122

2223
# include <boost/type_traits/transform_traits.hpp>
2324
# include <boost/type_traits/add_const.hpp>
2425
# include <boost/type_traits/add_reference.hpp>
26+
# include <boost/type_traits/is_same.hpp>
2527

28+
# include <boost/mpl/apply_if.hpp>
2629
# include <boost/mpl/if.hpp>
30+
# include <boost/mpl/identity.hpp>
2731

2832
# include <boost/bind.hpp>
2933

@@ -71,74 +75,169 @@ namespace detail
7175
}
7276
};
7377

78+
template <class Data, class Policies>
79+
struct datum
80+
{
81+
static PyObject* get(Data *p, PyObject* args_, PyObject*, Policies const& policies)
82+
{
83+
// find the result converter
84+
typedef typename Policies::result_converter result_converter;
85+
typedef typename boost::add_reference<Data>::type source;
86+
typename mpl::apply1<result_converter,source>::type cr;
87+
88+
if (!policies.precall(args_)) return 0;
89+
90+
PyObject* result = cr( *p );
91+
92+
return policies.postcall(args_, result);
93+
}
94+
95+
static PyObject* set(Data* p, PyObject* args_, PyObject*, Policies const& policies)
96+
{
97+
// check that each of the arguments is convertible
98+
typedef typename add_const<Data>::type target1;
99+
typedef typename add_reference<target1>::type target;
100+
arg_from_python<target> c0(PyTuple_GET_ITEM(args_, 0));
101+
102+
if (!c0.convertible()) return 0;
103+
104+
if (!policies.precall(args_)) return 0;
105+
106+
*p = c0(PyTuple_GET_ITEM(args_, 0));
107+
108+
return policies.postcall(args_, detail::none());
109+
}
110+
};
111+
112+
template <class T>
113+
struct default_getter_by_ref
114+
: mpl::and_<
115+
mpl::bool_<
116+
to_python_value<
117+
typename add_reference<typename add_const<T>::type>::type
118+
>::uses_registry
119+
>
120+
, is_reference_to_class<
121+
typename add_reference<typename add_const<T>::type>::type
122+
>
123+
>
124+
{
125+
};
126+
74127
// If it's a regular class type (not an object manager or other
75128
// type for which we have to_python specializations, use
76129
// return_internal_reference so that we can do things like
77130
// x.y.z = 1
78131
// and get the right result.
79132
template <class T>
80-
struct default_getter_policy
81-
{
82-
typedef typename add_reference<
83-
typename add_const<T>::type
84-
>::type t_cref;
85-
86-
BOOST_STATIC_CONSTANT(
87-
bool, by_ref = to_python_value<t_cref>::uses_registry
88-
&& is_reference_to_class<t_cref>::value);
89-
90-
typedef typename mpl::if_c<
91-
by_ref
92-
, return_internal_reference<>
93-
, return_value_policy<return_by_value>
94-
>::type type;
95-
};
96-
}
133+
struct default_member_getter_policy
134+
: mpl::if_<
135+
default_getter_by_ref<T>
136+
, return_internal_reference<>
137+
, return_value_policy<return_by_value>
138+
>
139+
{};
97140

98-
template <class C, class D>
99-
object make_getter(D C::*pm)
100-
{
101-
typedef typename detail::default_getter_policy<D>::type policy;
102-
103-
return objects::function_object(
104-
::boost::bind(
105-
&detail::member<D,C,policy>::get, pm, _1, _2
106-
, policy())
107-
, 1);
108-
109-
}
141+
template <class T>
142+
struct default_datum_getter_policy
143+
: mpl::if_<
144+
default_getter_by_ref<T>
145+
, return_value_policy<reference_existing_object>
146+
, return_value_policy<return_by_value>
147+
>
148+
{};
149+
150+
template <class D, class Policies>
151+
inline object make_getter(D* p, Policies const& policies, int)
152+
{
153+
return objects::function_object(
154+
::boost::bind(
155+
&detail::datum<D,Policies>::get, p, _1, _2
156+
, policies)
157+
, 0);
158+
}
159+
160+
template <class D>
161+
inline object make_getter(D* p, not_specified, long)
162+
{
163+
typedef typename default_datum_getter_policy<D>::type policies;
164+
return make_getter(p, policies(), 0L);
165+
}
110166

111-
template <class C, class D, class Policies>
112-
object make_getter(D C::*pm, Policies const& policies)
113-
{
167+
template <class C, class D, class Policies>
168+
inline object make_getter(D C::*pm, Policies const& policies, int)
169+
{
114170
return objects::function_object(
115171
::boost::bind(
116172
&detail::member<D,C,Policies>::get, pm, _1, _2
117173
, policies)
118174
, 1);
175+
}
176+
177+
template <class C, class D>
178+
inline object make_getter(D C::*pm, not_specified, long)
179+
{
180+
typedef typename default_member_getter_policy<D>::type policies;
181+
return make_getter(pm, policies(), 0L);
182+
}
183+
184+
template <class D, class Policies>
185+
inline object make_getter(D& d, Policies const& policies, ...)
186+
{
187+
return detail::make_getter(&d, policies, 0L);
188+
}
189+
190+
template <class D, class Policies>
191+
inline object make_setter(D* p, Policies const& policies, long)
192+
{
193+
return objects::function_object(
194+
::boost::bind(
195+
&detail::datum<D,Policies>::set, p, _1, _2
196+
, policies)
197+
, 1);
198+
}
199+
200+
template <class C, class D, class Policies>
201+
inline object make_setter(D C::*pm, Policies const& policies, long)
202+
{
203+
return objects::function_object(
204+
::boost::bind(
205+
&detail::member<D,C,Policies>::set, pm, _1, _2
206+
, policies)
207+
, 2);
208+
}
209+
210+
template <class D, class Policies>
211+
inline object make_setter(D& x, Policies const& policies, ...)
212+
{
213+
return detail::make_setter(&x, policies, 0L);
214+
}
119215
}
120216

121-
template <class C, class D>
122-
object make_setter(D C::*pm)
217+
template <class D, class Policies>
218+
inline object make_getter(D& d, Policies const& policies)
123219
{
124-
return objects::function_object(
125-
::boost::bind(
126-
&detail::member<D,C,default_call_policies>::set, pm, _1, _2
127-
, default_call_policies())
128-
, 2);
220+
return detail::make_getter(d, policies, 0L);
129221
}
130222

131-
template <class C, class D, class Policies>
132-
object make_setter(D C::*pm, Policies const& policies)
223+
template <class D>
224+
inline object make_getter(D& x)
133225
{
134-
return objects::function_object(
135-
::boost::bind(
136-
&detail::member<D,C,Policies>::set, pm, _1, _2
137-
, policies)
138-
, 2);
226+
return detail::make_getter(x, detail::not_specified(), 0L);
227+
}
228+
229+
template <class D, class Policies>
230+
inline object make_setter(D& x, Policies const& policies)
231+
{
232+
return detail::make_setter(x, policies, 0L);
233+
}
234+
235+
template <class D>
236+
inline object make_setter(D& x)
237+
{
238+
return detail::make_setter(x, default_call_policies(), 0L);
139239
}
140240

141-
142241
}} // namespace boost::python
143242

144243
#endif // DATA_MEMBERS_DWA2002328_HPP

0 commit comments

Comments
 (0)