[C++-sig] contained structure access

David Abrahams dave at boost-consulting.com
Tue Nov 5 22:37:18 CET 2002


Graeme Lufkin <gwl at u.washington.edu> writes:

> 	I've found some strange (I think) behavior in Boost.Python, and I've
> boiled it down to the example below.  (By the way, I'm new to
> Boost.Python, and am using it to get scripting language access to the
> C/C++ classes used in my astrophysics simulations.  I think it's going
> to work out great.)
> 	I'm exposing several C++ classes to Python.  Classes that are made of
> built-in types work great, and I can manipulate member variables when I
> def_readwrite() them.  Now go up a level, and imagine a class that holds
> these simpler classes.  I def_readwrite() the member variables of the
> higher-level class that are of type the simpler class.  But now when I
> access the members of the members, my assigning gets silently ignored. 
> Let me explain with code:
> 	Here's my .cpp file.  It defines two simple structs and exposes them to
> Python. (I'm using Boost 1.29.0)
> 
> struct Atom {
> 	double x;
> };
> 
> struct Holder {
> 	Atom a;
> };
> 
> #include <boost/python.hpp>
> using namespace boost::python;
> 
> BOOST_PYTHON_MODULE(Contained_Stuff) {
> 	class_<Atom>("Atom").def_readwrite("x", &Atom::x);
> 	class_<Holder>("Holder").def_readwrite("a", &Holder::a);	
> }
> 
> 	To illustrate the problem, here's a Python session with the compiled
> module:
> 
> >>> from Contained_Stuff import * 
> >>> at = Atom()
> >>> print at.x
> 0.0
> >>> at.x = 42
> >>> print at.x
> 42.0
> >>> h = Holder()
> >>> print h.a.x
> 0.0
> >>> h.a.x = 43
> >>> print h.a.x
> 0.0
> >>> h.a = at
> >>> print h.a.x
> 42.0

Nice reproducible case!

> 	I can create variables of type Atom, and get/set it's 'x' member
> variable fine.  I can also create variables of type Holder, and get/set
> its 'a' member variable (of type Atom).  However, when I try to modify
> the 'x' of the Holder's Atom, it is ignored.  I can recreate this
> situation using regular 100% Python classes, and it works as expected. 
> So, what am I doing wrong?

You have to remember how def_readwrite works. It creates a
property. If you look at the documentation at
http://www.boost.org/libs/python/doc/v2/class.html#class_-spec-modifiers
you'll see

   Effects:  this->add_property(name, make_getter(pm), make_setter(pm));

And if you look at
http://www.boost.org/libs/python/doc/v2/data_members.html#make_getter-spec
you'll see that make_getter with one argument uses the default call
policies, which copy of all return values. What's happening is that
the x member is getting set in the copy.

Instead, you could use

   this->add_property(
        name
        , make_getter(&Holder::a, return_internal_reference<>())
        , make_setter(&Holder::a));

Which should get you the behavior you want. I'll look into fixing it
so this is no longer needed, if I can find a few minutes to spend on
it.

> -- 
> 	- Graeme
> 	gwl at u.washington.edu
> "The experiment was inconclusive, so we had to use statistics."
> 
> 
> _______________________________________________
> C++-sig mailing list
> C++-sig at python.org
> http://mail.python.org/mailman/listinfo/c++-sig
> 

-- 
                    David Abrahams
dave at boost-consulting.com * http://www.boost-consulting.com





More information about the Cplusplus-sig mailing list