Hi there, given the following (simplified) scenario: typedef struct { PyObject_HEAD float bar[10]; } FooObject; I want to be able to set and retrieve the elements of bar from Python using e.g.
foo = Foo() foo.bar[4] = 1.23 x = foo.bar[4]
I have chosen an approach using 'PyArray_FromDimsAndData'. In fact I programmed it after studying 'arrayobject.c', namely the part in 'array_getattr' where the 'flat' attribute is accessed. foo_getattr(FooObject *self, char *name) { if (!strcmp(name, "bar")) { int n=10; PyObject *bar = PyArray_FromDimsAndData(1, &n, PyArray_FLOAT, (char*)self->bar); if (bar == NULL) return NULL; return bar; } return Py_FindMethod(foo_methods, (PyObject*)self, name); } And it works! :-) BUT how about refcounts here? 'PyArray_FromDimsAndData' will return an array which only contains a reference to foo's original bar array; that's why I can both set and access the latter the way described. And no memory leak is created. But what if I create a reference to foo.bar, and later delete foo, i.e.
b = foo.bar del foo
Now the data pointer in b refers to freed data! In the mentioned 'array_getattr' this apeears to be solved by increasing the refcount; in the above example this would mean 'Py_INCREF(self)' before returning 'bar'. Then if deleting 'foo', its memory is not freed because the refcount is not zero. But AFAICS in this case (as well as in the Numeric code) the INCREF prevents the object from EVER being freed. Who would DECREF the object? Or am I misunderstanding something here? In my actual code I can perfectly live with the above solution because I only need to access foo's data using 'foo.bar[i]' and probably never need to create a reference to 'bar' which might survive the actual 'foo' object. However, I want to program it the 'clean' way; any hints on how to do it properly would therefore be highly welcome. Cheers, Joachim
participants (4)
-
cookedmļ¼ arbutus.physics.mcmaster.ca
-
Joachim Saul
-
Konrad Hinsen
-
Travis Oliphant