From f2797ec26214b57f738edf7762409f98c54266ce Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Thu, 14 Nov 2002 17:41:13 +0000 Subject: [PATCH] Auto-detection of class memebers wrapped with make_getter() [SVN r16241] --- doc/news.html | 5 +++ doc/v2/data_members.html | 14 ++++++-- .../python/converter/builtin_converters.hpp | 5 +++ include/boost/python/data_members.hpp | 34 +++++++++++++++---- include/boost/python/to_python_value.hpp | 10 ++++++ test/data_members.cpp | 4 ++- test/data_members.py | 5 +++ todo.txt | 18 +++++++--- 8 files changed, 81 insertions(+), 14 deletions(-) diff --git a/doc/news.html b/doc/news.html index 0fca1204..6ae58360 100644 --- a/doc/news.html +++ b/doc/news.html @@ -29,6 +29,11 @@
+
14 November 2002
+ +
Auto-detection of class data members wrapped with make_getter
+
13 November 2002
Full Support for std::auto_ptr<> added.
diff --git a/doc/v2/data_members.html b/doc/v2/data_members.html index 1bf16cd4..0f015780 100644 --- a/doc/v2/data_members.html +++ b/doc/v2/data_members.html @@ -77,7 +77,15 @@ template <class C, class D, class Policies> C*, and returns the corresponding member D member of the C object, converted to_python. If policies is supplied, it will be applied to the - function as described here. + function as described here. Otherwise, + the library attempts to determine whether D is a + user-defined class type, and if so uses return_internal_reference<> + +
for Policies. Note that this test may inappropriately + choose return_internal_reference<> in some cases + when D is a smart pointer type. This is a known + defect.
Returns: An instance of object which holds the new Python @@ -147,8 +155,8 @@ BOOST_PYTHON_MODULE_INIT(data_members_example)

- 13 November, 2002 - + 13 November, 2002 +

© Copyright # include # include -# include +# include +# include # include # include +# include # include # include +# include +# include # include namespace boost { namespace python { @@ -44,7 +48,7 @@ namespace detail static PyObject* set(Data Class::*pm, PyObject* args_, PyObject*, Policies const& policies) { // check that each of the arguments is convertible - arg_from_python c0(PyTuple_GET_ITEM(args_, 0)); + arg_from_python c0(PyTuple_GET_ITEM(args_, 0)); if (!c0.convertible()) return 0; typedef typename add_const::type target1; @@ -55,22 +59,40 @@ namespace detail if (!policies.precall(args_)) return 0; - (c0(PyTuple_GET_ITEM(args_, 0)))->*pm = c1(PyTuple_GET_ITEM(args_, 1)); + (c0(PyTuple_GET_ITEM(args_, 0))).*pm = c1(PyTuple_GET_ITEM(args_, 1)); return policies.postcall(args_, detail::none()); } }; + + // If it's a regular class type (not an object manager or other + // type for which we have to_python specializations, use + // return_internal_reference so that we can do things like + // x.y.z = 1 + // and get the right result. + template + struct default_getter_policy + : mpl::if_c< + to_python_value< + typename add_reference< + typename add_const::type + >::type + >::uses_registry + , return_internal_reference<> + , return_value_policy + > + {}; } template object make_getter(D C::*pm) { - typedef return_value_policy default_policy; + typedef typename detail::default_getter_policy::type policy; return objects::function_object( ::boost::bind( - &detail::member::get, pm, _1, _2 - , default_policy()) + &detail::member::get, pm, _1, _2 + , policy()) , 1); } diff --git a/include/boost/python/to_python_value.hpp b/include/boost/python/to_python_value.hpp index 3b9cd76c..de5122a2 100644 --- a/include/boost/python/to_python_value.hpp +++ b/include/boost/python/to_python_value.hpp @@ -29,6 +29,11 @@ namespace detail static bool convertible(); PyObject* operator()(argument_type) const; + + // This information helps make_getter() decide whether to try to + // return an internal reference or not. I don't like it much, + // but it will have to serve for now. + BOOST_STATIC_CONSTANT(bool, uses_registry = false); }; @@ -41,6 +46,11 @@ namespace detail static bool convertible(); PyObject* operator()(argument_type) const; + + // This information helps make_getter() decide whether to try to + // return an internal reference or not. I don't like it much, + // but it will have to serve for now. + BOOST_STATIC_CONSTANT(bool, uses_registry = true); }; } diff --git a/test/data_members.cpp b/test/data_members.cpp index 5a87eeae..e5affba4 100644 --- a/test/data_members.cpp +++ b/test/data_members.cpp @@ -24,12 +24,13 @@ double get_fair_value(X const& x) { return x.value(); } struct Var { - Var(std::string name_) : name(name_), value(), name2(name.c_str()) {} + Var(std::string name_) : name(name_), value(), name2(name.c_str()), y(6) {} std::string const name; std::string get_name1() const { return name; } std::string const& get_name2() const { return name; } float value; char const* name2; + Y y; }; BOOST_PYTHON_MODULE(data_members_ext) @@ -51,6 +52,7 @@ BOOST_PYTHON_MODULE(data_members_ext) .def_readonly("name", &Var::name) .def_readonly("name2", &Var::name2) .def_readwrite("value", &Var::value) + .def_readonly("y", &Var::y) // Test return_by_value for plain values and for // pointers... return_by_value was implemented as a diff --git a/test/data_members.py b/test/data_members.py index c908f515..820b4f12 100644 --- a/test/data_members.py +++ b/test/data_members.py @@ -30,6 +30,11 @@ >>> v.get_name2() 'pi' +>>> v.y.x +6 +>>> v.y.x = -7 +>>> v.y.x +-7 ''' def run(args = None): diff --git a/todo.txt b/todo.txt index 3bcd16ac..6ee55157 100644 --- a/todo.txt +++ b/todo.txt @@ -1,11 +1,21 @@ -Wrap enums as a subclass of Python int +High Priority: +-------------- +Document builtin correspondences between builtiin Python types and C++ +types + + +Medium Priority: +---------------- + +Implement type_info streaming for GCC +(http://mail.python.org/pipermail/c++-sig/2002-June/001277.html) + +Low Priority: +------------ Write "inside the Python type system", a survey of typeobject.c in Python source -- may go hand-in-hand with enum wrapping Better overload resolution - choose best match -Implement type_info streaming for GCC -(http://mail.python.org/pipermail/c++-sig/2002-June/001277.html) -