[Numpy-discussion] subclassing array in c

Christoph Gohle christoph.gohle at mpq.mpg.de
Wed Mar 7 20:04:53 EST 2012


-----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-----



More information about the NumPy-Discussion mailing list