[C++-sig] When You Create an Python Object Using Boost.Python, How Do You Find Out Its Name?

Lawrence Spector Lawrence.Spector at CanfieldSci.com
Thu Jul 12 15:59:52 CEST 2007


That's a great point.  I definitely had a mistake in my code (which I wasn't seeing).  TestClassWrap should've been using a reference/pointer to the initial object.  Making this change made TestClass always have the same address -- which makes sense, since even upon a copy, it's just going to copy the address, so it's still pointing to a valid location.  Obviously, I could do this better with reference counting, but this was fine for illustration.

However, here's the caveat.  TestClassWrap has a different address.  Here's what I can see from the output of my test program and running the debugger to verify the callstack.

TestClassWrap constructor (from C++) - 0x0012FF10
TestClassWrap::output method (from Python code via Boost.Python: pyTestClass.attr("output")() - Python) - 0x993B90
TestClassWrap::output method (via Boost.Python exec() - Python) - 0x993B90
TestClassWrap::output method (via testClassWrapper.output() from C++) - 0x0012FF10
TestClassWrap destructor (from C++) - 0x0012FF10

[Note: TestClassWrap destructor never gets initiated for the Python copy -- most likely because I'm avoiding using Py_Finalize() due to other issues mentioned from a previous post.]

Anyway, I think this clearly shows that boost::python::object is making a copy.

The good news is, yes, had I done the initial sample properly, I can always just make a wrapper around a class to make sure it's keeps a reference to the initial class, and have it just make copies of the wrapper.

Now the question becomes, is there a better way to tell Boost.Python that I want to keep a reference to my initial object, or is it all a manual process where I *must* make a wrapper around every class in order to do the reference counting myself?

Please let me know.  I appreciate all of your assistance so far.

Thanks,

Lawrence


-----Original Message-----
From: c++-sig-bounces at python.org [mailto:c++-sig-bounces at python.org] On Behalf Of Nat Goodspeed
Sent: Wednesday, July 11, 2007 8:02 PM
To: Development of Python/C++ integration
Subject: Re: [C++-sig] When You Create an Python Object Using Boost.Python, How Do You Find Out Its Name?

> -----Original Message-----
> From: c++-sig-bounces at python.org [mailto:c++-sig-bounces at python.org]
On
> Behalf Of Lawrence Spector
> Sent: Tuesday, July 10, 2007 4:33 PM
> To: Development of Python/C++ integration
> Subject: Re: [C++-sig] When You Create an Python Object Using
> Boost.Python, How Do You Find Out Its Name?
>
> I illustrate the issue by printing the 'this' pointer at different
> sections.  Note that the memory locations are different depending on
how I
> call it.  Hopefully it makes sense.

[Nat] These are the key lines:

1.      TestClass testClass(std::cout, 3, 9.6f, 'Q');
2.      TestClassWrap testClassWrapper(testClass);
3.      boost::python::object pyTestClass(testClassWrapper);
4.      main_namespace["pyTestClass"] = pyTestClass;

It's clear from the definition of TestClassWrap that testClassWrapper
(line 2) instantiates a different TestClass object than testClass (line
1). As you asked earlier, the question is: how should line 3 behave? My
copy of the boost::python::object documentation says:

template <class T>
explicit object(T const& x);

Effects: converts x to python and manages a reference to it.
Throws: error_already_set and sets a Python TypeError exception if no
such conversion is possible.

So what does it mean to convert x to Python? boost::python::object
manages a PyObject*. (object::ptr() returns that PyObject*;
object::~object() decrements its ref count.)

But your testClassWrapper instance doesn't have a PyObject* or a ref
count. My assumption is that object's templated constructor allocates a
chunk of Python storage and constructs a fresh TestClassWrap instance
there.

Once that's in place, though, I'd assume that the assignment on line 4
above would NOT construct yet another instance. I would expect that
main_namespace["pyTestClass"] and your C++ variable pyTestClass should
both reference the same TestClassWrap instance.

If that's not what you're seeing (I haven't run your example) then I'll
have to defer to others to account for it.

> > -----Original Message-----
> > From: c++-sig-bounces at python.org [mailto:c++-sig-bounces at python.org]
> On
> > Behalf Of Lawrence Spector
> > Sent: Monday, July 09, 2007 5:35 PM
> > To: Development of Python/C++ integration
> > Subject: Re: [C++-sig] When You Create an Python Object Using
> > Boost.Python, How Do You Find Out Its Name?
> >
> > Any idea why?  Does the constructor of boost::python::object make a
> copy?
_______________________________________________
C++-sig mailing list
C++-sig at python.org
http://mail.python.org/mailman/listinfo/c++-sig



More information about the Cplusplus-sig mailing list