Skip to content

Commit f2797ec

Browse files
committed
Auto-detection of class memebers wrapped with make_getter()
[SVN r16241]
1 parent a217277 commit f2797ec

8 files changed

Lines changed: 81 additions & 14 deletions

File tree

doc/news.html

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,11 @@ <h2 align="center">News/Change Log</h2>
2929
<hr>
3030

3131
<dl class="page-index">
32+
<dt>14 November 2002</dt>
33+
34+
<dd>Auto-detection of class data members wrapped with <a href=
35+
"v2/data_members.html#make_getter-spec"><code>make_getter</code></a></dd>
36+
3237
<dt>13 November 2002</dt>
3338

3439
<dd>Full Support for <code>std::auto_ptr&lt;&gt;</code> added.</dd>

doc/v2/data_members.html

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,15 @@ <h2><a name="functions"></a>Functions</h2>
7777
<code>C*</code>, and returns the corresponding member <code>D</code>
7878
member of the <code>C</code> object, converted <code>to_python</code>.
7979
If <code>policies</code> is supplied, it will be applied to the
80-
function as described <a href="CallPolicies.html">here</a>.</dt>
80+
function as described <a href="CallPolicies.html">here</a>. Otherwise,
81+
the library attempts to determine whether <code>D</code> is a
82+
user-defined class type, and if so uses <code><a href=
83+
"return_internal_reference.html#return_internal_reference-spec">return_internal_reference</a>&lt;&gt;</code></dt>
84+
85+
<dt>for <code>Policies</code>. Note that this test may inappropriately
86+
choose <code>return_internal_reference&lt;&gt;</code> in some cases
87+
when <code>D</code> is a smart pointer type. This is a known
88+
defect.</dt>
8189

8290
<dt><b>Returns:</b> An instance of <a href=
8391
"object.html#object-spec">object</a> which holds the new Python
@@ -147,8 +155,8 @@ <h2><a name="examples"></a>Example</h2>
147155

148156
<p>
149157
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
150-
13 November, 2002
151-
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
158+
13 November, 2002
159+
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
152160
</p>
153161

154162
<p><i>&copy; Copyright <a href=

include/boost/python/converter/builtin_converters.hpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,11 @@ namespace detail
3838
struct builtin_to_python
3939
{
4040
static bool convertible() { return true; }
41+
42+
// This information helps make_getter() decide whether to try to
43+
// return an internal reference or not. I don't like it much,
44+
// but it will have to serve for now.
45+
BOOST_STATIC_CONSTANT(bool, uses_registry = false);
4146
};
4247
}
4348

include/boost/python/data_members.hpp

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,15 @@
99
# include <boost/python/detail/config.hpp>
1010
# include <boost/python/detail/wrap_python.hpp>
1111
# include <boost/type_traits/transform_traits.hpp>
12-
# include <boost/type_traits/cv_traits.hpp>
12+
# include <boost/type_traits/add_const.hpp>
13+
# include <boost/type_traits/add_reference.hpp>
1314
# include <boost/python/return_value_policy.hpp>
1415
# include <boost/python/return_by_value.hpp>
16+
# include <boost/python/return_internal_reference.hpp>
1517
# include <boost/python/object/function_object.hpp>
1618
# include <boost/python/arg_from_python.hpp>
19+
# include <boost/python/converter/builtin_converters.hpp>
20+
# include <boost/mpl/if.hpp>
1721
# include <boost/bind.hpp>
1822

1923
namespace boost { namespace python {
@@ -44,7 +48,7 @@ namespace detail
4448
static PyObject* set(Data Class::*pm, PyObject* args_, PyObject*, Policies const& policies)
4549
{
4650
// check that each of the arguments is convertible
47-
arg_from_python<Class*> c0(PyTuple_GET_ITEM(args_, 0));
51+
arg_from_python<Class&> c0(PyTuple_GET_ITEM(args_, 0));
4852
if (!c0.convertible()) return 0;
4953

5054
typedef typename add_const<Data>::type target1;
@@ -55,22 +59,40 @@ namespace detail
5559

5660
if (!policies.precall(args_)) return 0;
5761

58-
(c0(PyTuple_GET_ITEM(args_, 0)))->*pm = c1(PyTuple_GET_ITEM(args_, 1));
62+
(c0(PyTuple_GET_ITEM(args_, 0))).*pm = c1(PyTuple_GET_ITEM(args_, 1));
5963

6064
return policies.postcall(args_, detail::none());
6165
}
6266
};
67+
68+
// If it's a regular class type (not an object manager or other
69+
// type for which we have to_python specializations, use
70+
// return_internal_reference so that we can do things like
71+
// x.y.z = 1
72+
// and get the right result.
73+
template <class T>
74+
struct default_getter_policy
75+
: mpl::if_c<
76+
to_python_value<
77+
typename add_reference<
78+
typename add_const<T>::type
79+
>::type
80+
>::uses_registry
81+
, return_internal_reference<>
82+
, return_value_policy<return_by_value>
83+
>
84+
{};
6385
}
6486

6587
template <class C, class D>
6688
object make_getter(D C::*pm)
6789
{
68-
typedef return_value_policy<return_by_value> default_policy;
90+
typedef typename detail::default_getter_policy<D>::type policy;
6991

7092
return objects::function_object(
7193
::boost::bind(
72-
&detail::member<D,C,default_policy>::get, pm, _1, _2
73-
, default_policy())
94+
&detail::member<D,C,policy>::get, pm, _1, _2
95+
, policy())
7496
, 1);
7597

7698
}

include/boost/python/to_python_value.hpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,11 @@ namespace detail
2929

3030
static bool convertible();
3131
PyObject* operator()(argument_type) const;
32+
33+
// This information helps make_getter() decide whether to try to
34+
// return an internal reference or not. I don't like it much,
35+
// but it will have to serve for now.
36+
BOOST_STATIC_CONSTANT(bool, uses_registry = false);
3237
};
3338

3439

@@ -41,6 +46,11 @@ namespace detail
4146

4247
static bool convertible();
4348
PyObject* operator()(argument_type) const;
49+
50+
// This information helps make_getter() decide whether to try to
51+
// return an internal reference or not. I don't like it much,
52+
// but it will have to serve for now.
53+
BOOST_STATIC_CONSTANT(bool, uses_registry = true);
4454
};
4555
}
4656

test/data_members.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,13 @@ double get_fair_value(X const& x) { return x.value(); }
2424

2525
struct Var
2626
{
27-
Var(std::string name_) : name(name_), value(), name2(name.c_str()) {}
27+
Var(std::string name_) : name(name_), value(), name2(name.c_str()), y(6) {}
2828
std::string const name;
2929
std::string get_name1() const { return name; }
3030
std::string const& get_name2() const { return name; }
3131
float value;
3232
char const* name2;
33+
Y y;
3334
};
3435

3536
BOOST_PYTHON_MODULE(data_members_ext)
@@ -51,6 +52,7 @@ BOOST_PYTHON_MODULE(data_members_ext)
5152
.def_readonly("name", &Var::name)
5253
.def_readonly("name2", &Var::name2)
5354
.def_readwrite("value", &Var::value)
55+
.def_readonly("y", &Var::y)
5456

5557
// Test return_by_value for plain values and for
5658
// pointers... return_by_value was implemented as a

test/data_members.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,11 @@
3030
>>> v.get_name2()
3131
'pi'
3232
33+
>>> v.y.x
34+
6
35+
>>> v.y.x = -7
36+
>>> v.y.x
37+
-7
3338
'''
3439

3540
def run(args = None):

todo.txt

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,21 @@
1-
Wrap enums as a subclass of Python int
1+
High Priority:
2+
--------------
23

3-
Write "inside the Python type system", a survey of typeobject.c in
4-
Python source -- may go hand-in-hand with enum wrapping
4+
Document builtin correspondences between builtiin Python types and C++
5+
types
56

6-
Better overload resolution - choose best match
7+
8+
Medium Priority:
9+
----------------
710

811
Implement type_info streaming for GCC
912
(http://mail.python.org/pipermail/c++-sig/2002-June/001277.html)
1013

14+
Low Priority:
15+
------------
16+
Write "inside the Python type system", a survey of typeobject.c in
17+
Python source -- may go hand-in-hand with enum wrapping
18+
19+
Better overload resolution - choose best match
20+
1121

0 commit comments

Comments
 (0)