diff --git a/devsupApp/src/dbfield.c b/devsupApp/src/dbfield.c index 9e52c92..5dcfd39 100644 --- a/devsupApp/src/dbfield.c +++ b/devsupApp/src/dbfield.c @@ -196,6 +196,32 @@ static PyObject *pyField_getarray(pyField *self) #endif } +static PyObject *pyField_setlen(pyField *self, PyObject *args) +{ + rset *prset = dbGetRset(&self->addr); + Py_ssize_t len; + + if(!PyArg_ParseTuple(args, "n", &len)) + return NULL; + + if(self->addr.special!=SPC_DBADDR || + !prset || + !prset->put_array_info) + { + PyErr_SetString(PyExc_TypeError, "Not an array field"); + } + + if(len<1 || len > self->addr.no_elements) { + PyErr_Format(PyExc_ValueError, "Requested length %ld out of range [1,%lu)", + (long)len, (unsigned long)self->addr.no_elements); + return NULL; + } + + prset->put_array_info(&self->addr, len); + + Py_RETURN_NONE; +} + static PyObject* pyField_getTime(pyField *self) { DBLINK *plink = self->addr.pfield; @@ -239,6 +265,11 @@ static PyObject* pyField_getAlarm(pyField *self) return Py_BuildValue("ll", (long)sevr, (long)stat); } +static PyObject *pyField_len(pyField *self) +{ + return PyInt_FromLong(self->addr.no_elements); +} + static PyMethodDef pyField_methods[] = { {"name", (PyCFunction)pyField_name, METH_NOARGS, "Return Names (\"record\",\"field\")"}, @@ -250,10 +281,14 @@ static PyMethodDef pyField_methods[] = { "Sets field value from a scalar"}, {"getarray", (PyCFunction)pyField_getarray, METH_NOARGS, "Return a numpy ndarray refering to this field for in-place operations."}, + {"putarraylen", (PyCFunction)pyField_setlen, METH_VARARGS, + "Set array field length."}, {"getTime", (PyCFunction)pyField_getTime, METH_NOARGS, "Return link target timestamp as a tuple (sec, nsec)."}, {"getAlarm", (PyCFunction)pyField_getAlarm, METH_NOARGS, "Return link target alarm condtions as a tuple (severity, status)."}, + {"__len__", (PyCFunction)pyField_len, METH_NOARGS, + "Maximum number of elements storable in this field"}, {NULL, NULL, 0, NULL} }; diff --git a/devsupApp/src/devsup/_nullapi.py b/devsupApp/src/devsup/_nullapi.py index d40720b..d3edd14 100644 --- a/devsupApp/src/devsup/_nullapi.py +++ b/devsupApp/src/devsup/_nullapi.py @@ -168,10 +168,23 @@ class _Field(object): lock is held (ie withing :meth:`process `). """ + def putarraylen(self, len): + """Set the number of active elements in field's array. + + Requires that the underlying field be an array. + Must be less than the maximum length of the field. + """ + def getAlarm(self): """Returns a tuple (severity, status) with the condtion of the linked field. Only works for fields of type DBF_INLINK. """ + def __len__(self): + """Returns the maximum number of elements which may be stored in the field. + + This is always 1 for scalar fields. + """ + _hooks = {} diff --git a/testApp/test3.py b/testApp/test3.py index 4b14f22..fbe1cca 100644 --- a/testApp/test3.py +++ b/testApp/test3.py @@ -1,3 +1,4 @@ +from __future__ import print_function import numpy as np import scipy as sp @@ -5,10 +6,13 @@ from numpy.random import randint, uniform class WfSup(object): def __init__(self, rec, args): - self.arr = rec.field('VAL').getarray() - self.x = np.arange(rec.NELM) + self.fld = rec.field('VAL') + self.arr = self.fld.getarray() + assert(len(self.fld)==rec.NELM) + self.x = np.arange(len(self.fld)) self.phase = 0.0 + print("start",self) def detach(self, rec): pass @@ -17,7 +21,7 @@ class WfSup(object): pha = self.phase*np.pi/180.0 self.phase = np.fmod(self.phase+10.0, 360.0) - N=randint(1, rec.NELM) + N=randint(1, len(self.fld)) val=self.arr[:N] x=self.x[:N] @@ -28,8 +32,8 @@ class WfSup(object): np.sin(val, out=val) val[:]*=uniform(0.5,2.0) val[:]+=2 - - self.NORD = N + + self.fld.putarraylen(N) def build(rec, args): return WfSup(rec, args)