[Numpy-discussion] subclassing array in c

Christoph Gohlke cgohlke@uci....
Wed Mar 7 20:01:14 CST 2012


FWIW, this crashes on Windows with numpy 1.6.1 but not numpy 1.7-git 
debug build.

Christoph Gohlke


On 3/7/2012 5:36 PM, Val Kalatsky wrote:
>
> Tried it on my Ubuntu 10.10 box, no problem:
>
> 1) Saved as spampub.c
> 2) Compiled with (setup.py attached): python setup.py build_ext -i
> 3) Tested from ipython:
> In [1]: import spampub
> In [2]: ua=spampub.UnitArray([0,1,2,3.0],'liter')
> In [3]: ua
> Out[3]: UnitArray([ 0.,  1.,  2.,  3.])
> In [4]: ua.unit
> Out[4]: 'liter'
>
>
> On Wed, Mar 7, 2012 at 7:15 PM, Val Kalatsky <kalatsky@gmail.com
> <mailto:kalatsky@gmail.com>> wrote:
>
>
>     Seeing the backtrace would be helpful.
>     Can you do whatever leads to the segfault
>     from python run from gdb?
>     Val
>
>
>     On Wed, Mar 7, 2012 at 7:04 PM, Christoph Gohle
>     <christoph.gohle@mpq.mpg.de <mailto:christoph.gohle@mpq.mpg.de>> wrote:
>
>         -----BEGIN PGP SIGNED MESSAGE-----
>         Hash: SHA1
>
>         Hi,
>
>         I have been struggeling for quite some time now. Desperate as I
>         am, now I need help.
>
>         I was trying to subclass ndarrays in a c extension (see code
>         below) and do constantly get segfaults. I have been checking my
>         INCREF and DECREF stuff up and down but can't find the error.
>         Probably I got something completely wrong... anybody able to help?
>
>         Thanks,
>         Christoph
>         - -----------------
>         #include <Python.h>
>         #include <structmember.h>
>
>         #include <numpy/arrayobject.h>
>
>         static PyObject *SpamError;
>
>         typedef struct {
>           PyArrayObject base;
>           PyDictObject* unit;
>         } UnitArrayObject;
>
>         PyTypeObject unitArrayObjectType;
>
>         static int
>         checkunit(PyObject *unit1, PyObject *unit2) {
>           return PyObject_Compare(unit1, unit2);
>         }
>
>         static PyObject *
>         unitArray_new(PyTypeObject *cls, PyObject *args, PyObject *kwargs) {
>                 PyObject *data = NULL,
>                                  *unit = NULL;
>           PyArray_Descr* dtype = NULL;
>           PyObject *res = NULL, *tmp = NULL;
>
>                 if (!PyArg_ParseTuple(args, "OO|O&", &data, &unit,
>         PyArray_DescrConverter, &dtype)) {
>                         Py_XDECREF(dtype);
>                         return NULL;
>                 }
>
>           res = PyArray_FromAny(data, dtype, 0, 0, NPY_ENSURECOPY, NULL);
>                 if (res == NULL) {
>                         Py_XDECREF(dtype);
>             //TODO: raise exception?
>                         return NULL;
>                 }
>
>                 if (PyObject_IsInstance(data, (PyObject*)cls)) {
>                         if (unit!=NULL &&
>         !checkunit((PyObject*)((UnitArrayObject*)data)->unit,unit)) {
>                                 Py_XDECREF(res);
>                                 //TODO: raise exception
>                                 return NULL;
>                         }
>                 } else {
>                         if (PyObject_IsTrue(unit)) {
>               tmp = res;
>                                 res = PyArray_View((PyArrayObject*)res,
>         NULL, &unitArrayObjectType);
>               if (tmp!=res) {
>                 Py_XDECREF(tmp);
>               }
>               ((UnitArrayObject*)res)->unit = (PyDictObject*)unit;
>               Py_INCREF(unit);
>               if (unit!=NULL) {
>               }
>                         }
>                 }
>                 return res;
>         }
>
>         static PyObject*
>         unitArray__array_finalize__(PyObject* new, PyObject* args) {
>                 PyObject *attr = NULL, *tmp = NULL;
>           PyObject *parent = NULL;
>
>           if (!PyArg_ParseTuple(args, "O", &parent)) {
>             return NULL;
>           }
>            if (parent!=NULL) {
>              attr = PyObject_GetAttrString(parent, "unit");
>              if (attr == NULL) {
>                 //parent has no 'unit' so we make a new empty one
>                attr = PyDict_New();
>                PyErr_Clear();
>              }
>            }
>           tmp = (PyObject*)((UnitArrayObject*)new)->unit;
>             ((UnitArrayObject*)new)->unit = (PyDictObject*)attr;
>
>           Py_INCREF(Py_None);
>           return Py_None;
>         }
>
>         static PyObject*
>         unitArray__array_wrap__(PyObject *self, PyObject *args) {
>                 PyObject *array = NULL, *context = NULL;
>
>                 if (!PyArg_ParseTuple(args, "OO", array, context)) {
>                         //TODO: raise exception
>                         return NULL;
>                 }
>
>                 printf("%s",PyString_AsString(PyObject_Str(context)));
>
>           Py_INCREF(array);
>           return array;
>         }
>
>
>         static PyMethodDef unitArrayMethods[] = {
>           {"__array_finalize__", unitArray__array_finalize__,
>         METH_VARARGS, "array finalize method"},
>           {"__array_wrap__", unitArray__array_wrap__, METH_VARARGS,
>         "array wrap method"},
>           {NULL, NULL, 0, NULL}
>         };
>
>         static PyMemberDef unitArrayMembers[] = {
>           {"unit", T_OBJECT, offsetof(UnitArrayObject, unit),  0,
>         "dictionary containing unit info."},
>           {NULL, 0, 0, 0, NULL}
>         };
>
>         PyTypeObject unitArrayObjectType = {
>                 PyObject_HEAD_INIT(NULL)
>                 0,                              /* ob_size        */
>         "spam.UnitArray",               /* tp_name        */
>                 sizeof(UnitArrayObject),                /* tp_basicsize   */
>                 0,                              /* tp_itemsize    */
>                 0,                              /* tp_dealloc     */
>                 0,                              /* tp_print       */
>                 0,                              /* tp_getattr     */
>                 0,                              /* tp_setattr     */
>                 0,                              /* tp_compare     */
>                 0,                              /* tp_repr        */
>                 0,                              /* tp_as_number   */
>                 0,                              /* tp_as_sequence */
>                 0,                              /* tp_as_mapping  */
>                 0,                              /* tp_hash        */
>                 0,                              /* tp_call        */
>                 0,                              /* tp_str         */
>                 0,                              /* tp_getattro    */
>                 0,                              /* tp_setattro    */
>                 0,                              /* tp_as_buffer   */
>                 Py_TPFLAGS_DEFAULT,             /* tp_flags       */
>         "A numpy array with units",     /* tp_doc         */
>           0,        /* traverseproc */
>           0,        /* tp_clear*/
>           0,        /* tp_richcompare */
>           0,        /* tp_weaklistoffset */
>           0,        /* tp_iter */
>           0,        /* tp_iternext */
>           unitArrayMethods,        /* tp_methods */
>           unitArrayMembers,        /* tp_members */
>           0,        /* tp_getset */
>           0,        /* tp_base*/
>           0,        /* tp_dict */
>           0,        /* tp_descr_get*/
>           0,        /* tp_descr_set */
>           0,        /* tp_dictoffset */
>           0,        /* tp_init */
>           0,        /* tp_alloc */
>           unitArray_new /* tp_new */
>         };
>
>
>         static PyMethodDef SpamMethods[] = {
>             {NULL, NULL, 0, NULL}        /* Sentinel */
>         };
>
>         PyObject *unitArray = NULL;
>         PyMODINIT_FUNC
>         initspampub(void)
>         {
>           import_array();
>
>           PyObject *m;
>
>           Py_INCREF(&PyArray_Type);
>           unitArrayObjectType.tp_base = &PyArray_Type;
>
>           if (PyType_Ready(&unitArrayObjectType) < 0)
>             return;
>
>
>           m = Py_InitModule3("spampub", SpamMethods, "some tests and a
>         array type with units.");
>           if (m == NULL)
>             return;
>
>           SpamError = PyErr_NewException("spampub.error", NULL, NULL);
>           Py_INCREF(SpamError);
>           PyModule_AddObject(m, "error", SpamError);
>           Py_INCREF(&unitArrayObjectType);
>           PyModule_AddObject(m, "UnitArray", (PyObject
>         *)&unitArrayObjectType);
>           (void) Py_InitModule("spampub", SpamMethods);
>
>         }
>
>
>         -----BEGIN PGP SIGNATURE-----
>         Version: GnuPG/MacGPG2 v2.0.14 (Darwin)
>
>         iEYEARECAAYFAk9YBbkACgkQLYu25rCEIzsExQCggHg0e0ibYP3bEsAE0Ce8Rbm3
>         qOcAoKwuTuE4BDZgrqNpwISgMS6uSMnO
>         =Qtek
>         -----END PGP SIGNATURE-----
>         _______________________________________________
>         NumPy-Discussion mailing list
>         NumPy-Discussion@scipy.org <mailto:NumPy-Discussion@scipy.org>
>         http://mail.scipy.org/mailman/listinfo/numpy-discussion
>
>
>
>
>
> _______________________________________________
> NumPy-Discussion mailing list
> NumPy-Discussion@scipy.org
> http://mail.scipy.org/mailman/listinfo/numpy-discussion


More information about the NumPy-Discussion mailing list