[C++-sig] Mapping an entire data structure over to a single Python instance. (Newbie question)

David Abrahams dave at boost-consulting.com
Sun Aug 14 21:36:46 CEST 2005

"Gerard Murphy" <g.j.murphy at sageserpent.com> writes:

> 3. I'd like to expose these conceptual classes to Python, mapping over
> these instances of 'DataStructure' mentioned above to Python objects -
> but with the Python class changing depending on what instance of
> 'DataStructure' is being mapped.

Is that an important feature of the system?

> The classes of the Python objects would be dynamically created by
> construction of a 'class_' object:-
>   // Somewhere this line will be repeatedly executed...
>   boost::python::class_<DataStructure> classObject(name);

No, that won't work.

What you can do is use Python's metaclass API.

Export your C++ DataStructure class once.  

       object data_structure
           = class_<DataStructure>( ... )

Then get its metaclass:

     object meta = object(

Now you can manufacture distinct subclasses on-the-fly:

    object new_subclass = meta(
        "name-of-subclass", python::make_tuple(data_structure),

> I'm assuming that although the class_ object will be destroyed at each
> repetition, the corresponding Python class lives on afterwards. It isn't a
> problem if this is not the case, as I could always manage these objects in a
> long-lived container or on the heap or whatever.
> What I intend to do is to dynamically add properties to 'classObject'
> that use the name of the property to fetch the appropriate associated
> value from the map. This would be done once per repetition, so that each
> repetition would create a brand new Python class.

I suggest you don't do that either.  It would be better to implement a
__getattr__ method in your exported DataStructure.

       object getattr(DataStructure& ds, std::string name)
           return object( ...lookup name in ds... );

       object data_structure
           = class_<DataStructure>( ... )
                .def("__getattr__", getattr)

For this you'll need to export class_<AbstractValue> and
class_<ConcreteValue<T> > for each ConcreteValue<T> you are using.

> To be a bit more specific, I want to call 'classObject.add_property()' with
> an application of boost::bind to a template function instantiation that
> takes a name, looks up the associated value in the map, dynamically
> casts to the template type parameter and returns the value.
> I can ask an exemplar map to walk itself so that on behalf of a set of maps
> sharing the same common structure, it will populate a single class
> object with the appropriate properties.

Doing it with add_property is going to be a bear.  Why would you want
to do that?

> *** Now for the questions ***
> OK, that's what I want to do ... but can I do the following first:-
> i) Can I construct more than one instance of 'class_<DataStructure>'
> using lots of different names as arguments at each construction
> call?  


Dave Abrahams
Boost Consulting

More information about the Cplusplus-sig mailing list