On Tue, Feb 12, 2013 at 5:11 AM, Sturla Molden <
stu...@molden.no> wrote:
> On 11.02.2013 17:29, Chris Barker - NOAA Federal wrote:
>
>> I'm still a bit confused -- Python objects are Python-specific, so if
>> you store them in a C+ container your C++ code that works with those
>> objects would have to know about Python objects. Or is the container
>> class itself the entire "core algorithm"?
>
>
> Python objects are allocated by Python, so we could e.g. have
>
> std::vector<PyObject*>
>
> but never
>
> std::vector<PyObject>
>
> However, in the first case the C++ vector will keep the object alive, i.e.
> that object that the PyObject* pointer is pointing to. And that will require
> reference counting. That is one of the reasons it is recommended to use CXX
> and not the Python C API directly when writing Python extensions manually in
> C++.
>
> What we need then is a small C++ class that stores a PyObject* internally
> and keeps track of the reference counting. The container itsef (e.g.
> std::vector<T>) does not need to know about Python objects. But the wrapper
> class for the PyObject* will use its constructor and destructor to incref
> and decref. Incref and decref will be called deterministically (and thus in
> the correct place) because of the RAII nature of C++. So the C++ container
> does not need to know about references.
Yep, this was option (2). I've even implemented such a class myself
(as I'm sure have several others.)
> But whenever a Python object is used
> as a C++ template parameter, Cython should insert the C++ wrapper class
> instead.
We could provide such a class explicitly in the Python API, e.g.
from cython import PyRef
cdef vector<PyRef[Foo]> v
v.push_back(PyRef(Foo())
cdef Foo foo =
v.at(0).Get()
which would do the right thing. We would have to add some support in
the compiler for this, at the very least avoiding a warning for an
object "template" parameter. We could consider adding special syntax
to deal with this, but I don't see how to make it completely
transparent without "cdef Foo" becoming ambiguous (e.g. in a method
signature, though one can't rule out being able to do fancy-enough
things with assignment operators...).
On this flip side, there's the idea of adding syntax for a borrowed
reference, e.g.
cdef Foo f = ...
cdef Foo* borrowed_foo = &f # does not keep f alive, just like C
cdef Foo f2 = f[0]
though this does run into sticky issues, like having to dis-allow.
cdef Foo* borrowed_foo = malloc(???)
> But until then, using Python objects as template parameters should
> probably be disallowed.
Yes.
- Robert