Getting object for PyObject (reference counting)
I can't find any definitive documentation that tells me how I should get a boost::python::object to wrap an existing PyObject*. I guess that there's a way to do it that uses an existing reference, and a way that takes an extra reference. -- murrayc@murrayc.com www.murrayc.com www.openismus.com
The trick is to use boost::python::handle: http://www.boost.org/doc/libs/1_38_0/libs/python/doc/v2/handle.html For example: object python_file((handle<>(borrowed(obj_ptr)))); ----- Original Message ---- From: Murray Cumming <murrayc@murrayc.com> To: cplusplus-sig@python.org Sent: Friday, February 27, 2009 1:33:10 AM Subject: [C++-sig] Getting object for PyObject (reference counting) I can't find any definitive documentation that tells me how I should get a boost::python::object to wrap an existing PyObject*. I guess that there's a way to do it that uses an existing reference, and a way that takes an extra reference. -- murrayc@murrayc.com www.murrayc.com www.openismus.com _______________________________________________ Cplusplus-sig mailing list Cplusplus-sig@python.org http://mail.python.org/mailman/listinfo/cplusplus-sig
On Fri, 2009-02-27 at 07:35 -0800, Ralf W. Grosse-Kunstleve wrote:
The trick is to use boost::python::handle:
http://www.boost.org/doc/libs/1_38_0/libs/python/doc/v2/handle.html
For example:
object python_file((handle<>(borrowed(obj_ptr))));
Thanks, but like much of the documentation, I find that page very unclear. Is there anything that states more obviously what should be done in the two cases I mentioned.
I can't find any definitive documentation that tells me how I should get a boost::python::object to wrap an existing PyObject*. I guess that there's a way to do it that uses an existing reference, and a way that takes an extra reference.
-- Murray Cumming murrayc@murrayc.com www.murrayc.com www.openismus.com
Murray Cumming wrote:
On Fri, 2009-02-27 at 07:35 -0800, Ralf W. Grosse-Kunstleve wrote:
The trick is to use boost::python::handle:
http://www.boost.org/doc/libs/1_38_0/libs/python/doc/v2/handle.html
For example:
object python_file((handle<>(borrowed(obj_ptr))));
Thanks, but like much of the documentation, I find that page very unclear. Is there anything that states more obviously what should be done in the two cases I mentioned.
The best documentation I could find was this page on the Python wiki, taken from a email to this list: http://wiki.python.org/moin/boost.python/handle The only error is that references to "null_ok" should be "allow_null". At least that's the way I got it to work. -- Anthony Foglia Princeton Consultants (609) 987-8787 x233
Murray Cumming wrote:
I can't find any definitive documentation that tells me how I should get a boost::python::object to wrap an existing PyObject*. I guess that there's a way to do it that uses an existing reference, and a way that takes an extra reference.
You can construct a boost::python::object with a boost::python::handle<>. boost::python::handle<> is sort of a "smart" PyObject *. It manages the python object reference count automatically. When you create a boost::python::handle<> you can tell it whether to bump the reference count or not. Given a PyObject *p: // Use with a "new reference" -- *doesn't* bump ref count. handle<>(p); // Use with a "borrowed reference" -- *does* bump ref count. handle<>(borrowed(p)); Alex
On Fri, 2009-02-27 at 08:34 -0800, Alex Mohr wrote:
Murray Cumming wrote:
I can't find any definitive documentation that tells me how I should get a boost::python::object to wrap an existing PyObject*. I guess that there's a way to do it that uses an existing reference, and a way that takes an extra reference.
You can construct a boost::python::object with a boost::python::handle<>. boost::python::handle<> is sort of a "smart" PyObject *. It manages the python object reference count automatically.
Oh, I assumed that boost::python::object did this already. If not, is there any reason not to use boost::python::handle<boost::python::object> everywhere instead of a boost::python::object? One of my main reasons for using boost::python instead of the C API is to avoid worrying so much about the reference counting. For instance, I don't want to explicitly increment the ref when returning a PyObject, or remember whether I should take a ref when given a PyObject from various functions.
When you create a boost::python::handle<> you can tell it whether to bump the reference count or not. Given a PyObject *p:
// Use with a "new reference" -- *doesn't* bump ref count. handle<>(p);
// Use with a "borrowed reference" -- *does* bump ref count. handle<>(borrowed(p));
Alex _______________________________________________ Cplusplus-sig mailing list Cplusplus-sig@python.org http://mail.python.org/mailman/listinfo/cplusplus-sig -- Murray Cumming murrayc@murrayc.com www.murrayc.com www.openismus.com
Murray Cumming wrote:
On Fri, 2009-02-27 at 08:34 -0800, Alex Mohr wrote:
Murray Cumming wrote:
I can't find any definitive documentation that tells me how I should get a boost::python::object to wrap an existing PyObject*. I guess that there's a way to do it that uses an existing reference, and a way that takes an extra reference. You can construct a boost::python::object with a boost::python::handle<>. boost::python::handle<> is sort of a "smart" PyObject *. It manages the python object reference count automatically.
Oh, I assumed that boost::python::object did this already.
If not, is there any reason not to use boost::python::handle<boost::python::object> everywhere instead of a boost::python::object?
One of my main reasons for using boost::python instead of the C API is to avoid worrying so much about the reference counting. For instance, I don't want to explicitly increment the ref when returning a PyObject, or remember whether I should take a ref when given a PyObject from various functions.
I believe, but could be wrong, that boost::python::objects must be made from handles. If not that's not a requirement, it's at least a strong suggestion. That way, the underlying handle in the object will handle the reference counting for you. The way I understand it, the handle takes care of the reference counting, and the object is a wrapper to make it easier to interact with the pointer to PyObject in a more OO-like manner. Also, I'm not sure you can make a boost::python::handle<boost::python::object>. The instance the handle points to should be laid out like a PyObject. (Remember, the underlying Python code is C-based, so pointer layout is required to start the same to approximate inheritance.) I don't think boost::python::object can make that guarantee. -- Anthony Foglia Princeton Consultants (609) 987-8787 x233
Oh, I assumed that boost::python::object did this already.
It does. Think of bp::handle<> as a low-level, bare-bones, smart PyObject*. Think of bp::object as that, *plus* all the fancy c++ API that maps to python API (like obj.attr("foo"), []-operator, ()-operator, etc). I believe bp::object holds a handle<> internally.
If not, is there any reason not to use boost::python::handle<boost::python::object> everywhere instead of a boost::python::object?
Don't do that. You can't do that. It won't compile. Use bp::object everywhere unless you're convinced you have a good reason to do otherwise. If you have a PyObject *p and you want a bp::object, construct it via: object(handle<>(p)) // when p's a new reference object(handle<>(borrowed(p))) // when p's a borrowed reference
One of my main reasons for using boost::python instead of the C API is to avoid worrying so much about the reference counting. For instance, I don't want to explicitly increment the ref when returning a PyObject, or remember whether I should take a ref when given a PyObject from various functions.
Yup. Just use bp::object everywhere. I recommend you read through the reference manual: http://www.boost.org/doc/libs/1_38_0/libs/python/doc/v2/object.html http://www.boost.org/doc/libs/1_38_0/libs/python/doc/v2/handle.html Also look at the tutorials and examples and tests in the boost.python distribution. Alex
On Fri, 2009-02-27 at 15:18 -0800, Alex Mohr wrote: [snip]
If you have a PyObject *p and you want a bp::object, construct it via:
object(handle<>(p)) // when p's a new reference
I find that I have to split the handle and object over two lines. If I do this boost::python::object cppobject(boost::python::handle<>(cObject)); and then something like this: if(!cppobject.ptr()) doSomething() then I get this weird compiler error on the if() line: glom/python_embed/glom_python.cc:229: error: request for member ‘ptr’ in ‘cppobject’, which is of non-class type ‘boost::python::api::object(boost::python::handle<_object>)’ It's as if doing it on one line has changed the type. Maybe I've discovered some weird bug with g++ 4.4
object(handle<>(borrowed(p))) // when p's a borrowed reference
However, this works fine, when it's what I want. -- murrayc@murrayc.com www.murrayc.com www.openismus.com
On 02/11/2010 07:18 AM, Murray Cumming wrote:
On Fri, 2009-02-27 at 15:18 -0800, Alex Mohr wrote: [snip]
If you have a PyObject *p and you want a bp::object, construct it via:
object(handle<>(p)) // when p's a new reference
I find that I have to split the handle and object over two lines. If I do this boost::python::object cppobject(boost::python::handle<>(cObject)); and then something like this: if(!cppobject.ptr()) doSomething()
then I get this weird compiler error on the if() line:
glom/python_embed/glom_python.cc:229: error: request for member ‘ptr’ in ‘cppobject’, which is of non-class type ‘boost::python::api::object(boost::python::handle<_object>)’
It's as if doing it on one line has changed the type.
It does ! In C++, if something may be interpreted as a declaration, it is a declaration. And in the above case, the first line may be interpreted as a declaration of a function "cppobject" returning a bp::object, taking a handle<>. If you split things into three statements, by first instantiating a (named) handle<>, then pass that to the cppobject constructor, the error will go away, since that line then is no longer ambiguous. HTH, Stefan -- ...ich hab' noch einen Koffer in Berlin...
participants (5)
-
AFoglia@princeton.com -
Alex Mohr -
Murray Cumming -
Ralf W. Grosse-Kunstleve -
Stefan Seefeld