[C++-sig] Re: vector<foo*> -> list, preserving identity

Raoul Gough RaoulGough at yahoo.co.uk
Mon Dec 1 19:04:49 CET 2003


Jacek Generowicz <jacek.generowicz at cern.ch> writes:

> Raoul Gough <RaoulGough at yahoo.co.uk> writes:
>
>> Jacek Generowicz <jacek.generowicz at cern.ch> writes:
>
> [snip]
>
>> > How should I write a converter for the std::vector<foo*>, in order to
>> > preserve the identity of the foos ?
>> >
>> > (In the library I am wrapping, the return type of makefoos is actually
>> > const std::vector<const foo*>&)
>> 
>> I'm not sure how you would handle this, except by switching to
>> boost::shared_ptr instead of plain pointers. You would end up with
>> something like this:
>> 
>> std::vector<boost::shared_ptr<const foo> > makefoos(int n) {
>>   // ...
>> }
>
> Unfortunately "makefoos" is part of a library over which I have no
> control, so I cannot make it return shared pointers.

Bummer.

>
>> BOOST_PYTHON_MODULE( nocopy ) {
>>   class_<foo, boost::shared_ptr<foo> >("foo", no_init)
>>     .def("pointer", &foo::pointer);
>> 
>>   class_<std::vector<boost::shared_ptr<foo const> > > ("foo_vector")
>>     .def (SOMETHING<std::vector<boost::shared_ptr<foo const> >());
>> 
>>   def ("makefoos", makefoos);
>> }
>> 
>> Where SOMETHING would use either the current indexing suite (available
>> from CVS)
>
> Once again, I am obliged to use the local offical Boost version
> (1.30.2, at the moment), as that is what my users have. The Boost
> version I use is beyond my control.

OK. That still leaves the boost::python::list class.

>
> How does reference_existing_object work?  Using it as the return value
> policy for functions returning foo* preserves identity just fine.
> It's just when I get a whole vector of them and try to put them in a
> Python list that I don't seem to manage to avoid copying the objects
> themselves.

I've never actually used reference_existing_object, but if you think
about it, a reference to an existing vector object won't really help
you access the void * pointers that it contains. What you could
probably do is something along these lines (untested):

  typedef std::vector<foo const *> foo_ptr_vector;
  typedef foo const * (foo_ptr_vector::*memfn_type)(size_t) const;
  class_<> ("foo_ptr_vector")
    .def ("__getitem__"
        , static_cast<memfn_type>(&foo_ptr_vector::at)
        , return_value_policy<reference_existing_object>());

Providing __getitem__ will allow you to use a foo_ptr_vector from
Python via things like vec[n] or "for x in vec".

Alternatively, you might still be able to use a boost::python::list by
appending boost::shared_ptr objects that have do-nothing deleters
(search for "custom deallocator" in the shared_ptr docs). This could
be a better solution than trying to expose the vector interface, I
guess. Any way you cut it though, plain pointers won't play nicely
with Python.


-- 
Raoul Gough.
export LESS='-X'





More information about the Cplusplus-sig mailing list