[C++-sig] copy constructors and multiple instances
Jim Bosch
talljimbo at gmail.com
Thu Sep 1 20:11:25 CEST 2011
On 09/01/2011 07:03 AM, Josh Stratton wrote:
> In my particular scene I have a Scene class, which operates as kind of
> a context for my operations and holds all the meshes in the scene. I
> send my scene down to the python side so import methods will import
> into the containers in the scene object. For example,
> addMeshFromFile(scene, fileName) which puts the data from the file
> into the scene object. However, if the scene object isn't be
> returned, it seems I'm just copying the scene object (which might be
> memory expensive), adding the data to the copy, and throwing the copy
> away as I don't return it and it doesn't affect my original scene
> object in C++ that I passed in. I assume this is a fairly common
> problem and I need to rework my API somehow like providing a more
> robust copy constructor that does a shallow copy of my data
> containers. Still, I might have to reorganize it so I'm not passing
> my scene to python. If an object is copied every time, I think that
> might be memory prohibitive. I'm including my current source from
> github.
>
> // header file handling my scene and it's data
> https://github.com/strattonbrazil/Sunshine/blob/master/src/scene.h
>
> // functions for creating the bindings to python
> https://github.com/strattonbrazil/Sunshine/blob/master/src/python_bindings.cpp
>
> // python file which reads a file and adds it to the scene
> https://github.com/strattonbrazil/Sunshine/blob/master/src/objImporter.py
>
> Do I need to change need to change my copy constructor to do a more
> shallow copy? Maybe change my internal scene objects to pointers?
> Would this alleviate the memory issue?
A couple of comments:
- I'm a bit confused by your python_bindings.cpp file; did you paste
together several files? If not, I've never seen anyone try to define
more than one module in a single shared library, and I don't it's
supposed to work. You can wrap all of your objects in a single Python
module - the body of a BOOST_PYTHON_MODULE block is just a regular
function block, so you can include as many calls to class_ (and other
things) in there as you like. This might be part of the confusion about
needing to import modules from one of your earlier emails.
- You shouldn't have to do anything to the copy constructor to make this
work. Boost.Python is perfectly happy to pass things by reference or by
pointer. It could be that your QSharedPointers are getting in the way
of this. What is the signature of Mesh::buildByIndex? If the Scene is
passed by QSharedPointer, that might force a copy, because Boost.Python
only knows how to dereference the pointer, not copy it (in other words,
it doesn't want to assume it can copy the smart pointer, because some
smart pointers like auto_ptr can't be copied, so it's making a new
QSharedPointer from a copy-constructed object). If you can change it,
just make it take a Scene by reference - that will almost certainly
avoid making copies. Alternately, if you can use boost::shared_ptr
instead, that will also solve all of your problems. Unfortunately
support for non-boost shared pointers isn't great in Boost.Python right now.
- If you really want to ensure Boost.Python doesn't make unnecessary
copies of Scene, wrap it with:
class_<Scene,QSharedPointer<Scene>,boost::noncopyable>(...)
That will cause things that require copies to produce compiler errors,
and you can follow those errors to see exactly where the copy is
required. It will also keep you from returning Scene objects by value,
however, but it sounds like that might be desirable.
Jim
More information about the Cplusplus-sig
mailing list