[C++-sig] copy constructors and multiple instances

Jim Bosch talljimbo at gmail.com
Thu Sep 1 22:52:56 CEST 2011


On 09/01/2011 01:01 PM, Josh Stratton wrote:
>> - 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.
>
> I'm currently just embedding python, but I eventually wanted to extend
> it down the road.  I guess putting everything under the same macro
> makes more sense.  One thing I could find briefly skimming over the
> docs is creating submodules.  If the BOOST_PYTHON_MODULE is named
> "foo", is there some macro/function I can put inside of that handles
> submodules, so classes imported under it are imported in python such
> as "from foo.bar import SomeClass"?
>

To do that, you just need to add some pure Python and a directory 
structure.  If "foo" is a directory, and bar.so is a Boost.Python 
extension module (suffix is different on Windows, of course), you just 
need to have:

foo/__init__.py
foo/bar.so

But just like you can't have a pure-Python package+module structure in a 
single file, you can't do it in C++ either; you need to have a directory 
and the __init__.py file.

>> - 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.
>
> Switching to boost's shared_ptr shouldn't be difficult.
> Mesh::buildByIndex does take a shared-pointer, but if I understand
> correctly, switching to boost::shared_ptr<Scene>  should solve my
> issue.

Yup.  With boost::shared_ptr, you don't even need to include it as a 
template argument of class_, if you instead add the line:

boost::python::register_ptr_to_python< boost::shared_ptr<Scene> >();

This allows you to return shared_ptr to Python, but because a 
boost::shared_ptr can use an arbitrary deleter, Boost.Python can convert 
any wrapped Scene object (even one that doesn't hold a 
shared_ptr<Scene>) into a shared_ptr<Scene> with correct reference counting.

If you do include boost::shared_ptr<Scene> in the class_ template 
arguments, all Scene objects constructed in Python will be inside a 
shared_ptr, but because of the above, that isn't necessary unless you 
have functions that need to reset the shared_ptr itself.

Jim


More information about the Cplusplus-sig mailing list