Boost logo

Boost :

From: David Abrahams (abrahams_at_[hidden])
Date: 2001-01-19 23:19:05


----- Original Message -----
From: <rwgk_at_[hidden]>

> I am using the latest CVS snapshot of boost.
>
> We are trying to define BPL Python bindings for some C++ classes that
> we are developing. In particular, we have a container class that
> manages a set of a polymorphic objects. I have distilled the idea down
> to a relatively simple example, dynatype.cpp. This file is available
> in
> the boost egroup upload area:
>
> http://www.egroups.com/files/boost/dynatype.cpp
>
> This simple python script shows what we want to do:
>
> import dynatype
>
> # Container with variables of a polymorphic type.
> c = dynatype.container() # <container object at 1400523a0>
>
> # Possible type identifiers are 'int' or 'double'.
> c.declare('int', 'an_int')
> c.declare('double', 'a_double')
>
> # Get references to the variables in the container.
> i = c.get('an_int') # <dynavalue_int object at 1400523f0>
> d = c.get('a_double') # <dynavalue_double object at 140052440>
>
> # Change the values of the variables.
> i.set(3)
> d.set(3.1415)
>
> # Get them back (as Python integer or float).
> i.get() # 3
> d.get() # 3.1415
>
> # This proves that j.set() changes the contents of the container.
> j = c.get('an_int') # <dynavalue_int object at 1400523f0>
> j.get() # 3
> j.set(4)
> i.get() # 4
>
>
> This actually works, but there are a few issues:
>
> 0. Note that the values in the container are based on an abstract
> C++ class "dynabase."
>
> The actual values are C++ objects of the type "dynavalue<int>"
> and "dynavalue<double>."

This looks like a good place to take advantage of the "any" class template
which Kevlin Henney is currently preparing for release. The version which
passed the boost review process is at:

http://www.egroups.com/files/boost/any/

> The container is implemented using a
> std::map<string, boost::shared_ptr<dynabase> >
>
> 1. The Python c.get() is bound to the C++ function py_get().
> Somewhere inside this function we have to have a dynamic_cast<>()
> from a shared_ptr<dynabase>
> to a shared_ptr<dynavalue<int> >
> or a shared_ptr<dynavalue<double> >.
>
> To do this, I had to modifiy smart_ptr.hpp (line 139):
>
> template<typename Y>
> shared_ptr(const shared_ptr<Y>& r) : px(dynamic_cast<T*>(r.px))
> {
> ++*(pn = r.pn);
> }
>
> Questions:
> 1. Is there a better way of doing this?

I think that "any" could save you from this hack.

> 2. If not, would there be a way of having both the old and my
> modified copy constructor, and could this become part of
> the standard smart_ptr.hpp?

Sorry, I don't think so. Your version makes shared_ptr unusable with types
that don't have virtual functions. It also adds a reference count even when
r doesn't in fact point to a T, causing a leak.

> 2. There is a horrible memory leak associated with the use of c.get().
> I am pretty sure that this is due to the following invocation of
> to_python():
>
> boost::shared_ptr<dynavalue<int> > dvi(dv);
> return BOOST_PYTHON_CONVERSION::to_python(dvi);
>
> What is wrong with this use of to_python()?

Nothing, as far as I can tell, but you may be leaking due to your
modifications of shared_ptr.

-Dave


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk