[C++-sig] boost::python constructing object from PyObject *
David Abrahams
dave at boostpro.com
Wed Oct 29 21:55:48 CET 2008
on Wed Oct 29 2008, Hans Meine <hans_meine-AT-gmx.net> wrote:
> On Mittwoch 29 Oktober 2008, Dan Eloff wrote:
>> When creating an object from a PyObject *, how do you distinguish
>> between a PyObject pointer that is a new reference (must not be
>> increfed, but must be decrefed) versus a PyObject * that is a borrowed
>> reference? (should be increfed and decrefed)
>>
>> A very simple question for which there is no documented answer,
>> conflicting answers in the archives of this mailing list, and hours of
>> googling has turned up conflicting information.
>>
>> The best I could find was object(borrowed(ptr)) for new references and
>> object(handle<>(ptr)) for borrowed pointers. I'm not sure if that is
>> accurate, but if so that deserves a nomination for a terrible
>> interface award.
>>
>> Please someone put me out of my misery. What's the interface for this?
>
> IIRC I have complained about this in the past, too. I think it was actually
> discussed in the BPL tutorial (and only there AFAIK), but was eventually
> deleted (probably because it was not the best place for that kind of
> information).
>
> Actually, I have the same question as you, and the same impression that the
> above two ways are the "correct" ways. Err, no - you did swap the two,
> right?
Guidelines:
- handle, essentially a smart pointer. Use when necessary.
* a handle<> can be NULL, and maintains a reference count on the
object it points to
* handle<> y(null_ok(x)) allows y to become NULL
* handle<> y(x), where x is not the result of null_ok, never results
in a NULL y. An exception will be thrown if x is NULL
* handle<> y(borrowed(x)) presumes that *x is borrowed and thus
increments its reference count.
* handle<> y(x), where x is not the result of borrowed, presumes
that someone has already incremented the reference count on *x for
us.
* you can combine borrowed and null_ok in any order, so
handle<> y(borrowed(null_ok(x)))
and
handle<> y(null_ok(borrowed(x)))
are equivalent.
- object, a higher-level notion. Use wherever possible.
* an object can't be constructed from a raw PyObject* because
there's no information in that type about whether the refcount has
been incremented for this additional reference
* an object can only be constructed from a handle<>. Other
interfaces are not for public consumption and thus not
documented. Use at your own peril.
* an instance of object always "points to" something (maybe None).
If the constructor argument (handle) is NULL, an exception will be
thrown.
> Looking back at my code, I think I used boost::python::detail::new_reference.
>
> And for turning a Foo* pointer to an object of an exported class Foo, I used
> something as ugly as:
> bp::detail::new_reference(typename manage_new_object::apply<T *>::type()(p)
>
> AFAICS, I repeated my questions a total of three times (in the "How about
> class_<...>.enable_copy() ?" thead), but nobody answered so far.
The above should be a complete guide. Any questions?
--
Dave Abrahams
BoostPro Computing
http://www.boostpro.com
More information about the Cplusplus-sig
mailing list