[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