diff --git a/devsupApp/src/dbfield.c b/devsupApp/src/dbfield.c index d3ce91f..b949aba 100644 --- a/devsupApp/src/dbfield.c +++ b/devsupApp/src/dbfield.c @@ -4,12 +4,31 @@ #undef _XOPEN_SOURCE #include +#ifdef HAVE_NUMPY +#include +#endif #include #include #include #include +#ifdef HAVE_NUMPY +static int dbf2np_map[DBF_ENUM+1] = { + NPY_BYTE, + NPY_BYTE, + NPY_UBYTE, + NPY_INT16, + NPY_UINT16, + NPY_INT32, + NPY_UINT32, + NPY_FLOAT32, + NPY_FLOAT64, + NPY_INT16, +}; +static PyArray_Descr* dbf2np[DBF_ENUM+1]; +#endif + typedef struct { PyObject_HEAD @@ -152,6 +171,28 @@ static PyObject* pyField_putval(pyField *self, PyObject* args) Py_RETURN_NONE; } +static PyObject *pyField_getarray(pyField *self) +#ifdef HAVE_NUMPY +{ + int flags = NPY_CARRAY; + char *data=self->addr.pfield; + npy_int dims[1] = {self->addr.no_elements}; + PyArray_Descr *desc; + if(self->addr.field_type>DBF_ENUM) { + PyErr_SetString(PyExc_TypeError, "Can not map field type to numpy type"); + return NULL; + } + desc = dbf2np[self->addr.field_type]; + Py_XINCREF(desc); + return PyArray_NewFromDescr(&PyArray_Type, desc, 1, dims, NULL, data, flags, (PyObject*)self); +} +#else +{ + PyErr_SetNone(PyExc_NotImplementedError); + return NULL; +} +#endif + static PyMethodDef pyField_methods[] = { {"name", (PyCFunction)pyField_name, METH_NOARGS, "Return Names (\"record\",\"field\")"}, @@ -161,6 +202,8 @@ static PyMethodDef pyField_methods[] = { "Returns scalar version of field value"}, {"putval", (PyCFunction)pyField_putval, METH_VARARGS, "Sets field value from a scalar"}, + {"getarray", (PyCFunction)pyField_getarray, METH_NOARGS, + "Return a numpy ndarray refering to this field for in-place operations."}, {NULL, NULL, 0, NULL} }; @@ -222,6 +265,8 @@ static PyTypeObject pyField_type = { int pyField_prepare(void) { + size_t i; + pyField_type.tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE; pyField_type.tp_flags |= Py_TPFLAGS_HAVE_GETCHARBUFFER|Py_TPFLAGS_HAVE_NEWBUFFER; pyField_type.tp_methods = pyField_methods; @@ -231,6 +276,16 @@ int pyField_prepare(void) pyField_type.tp_new = PyType_GenericNew; if(PyType_Ready(&pyField_type)<0) return -1; + + import_array1(-1); + +#ifdef HAVE_NUMPY + for(i=0; i<=DBF_ENUM; i++) { + dbf2np[i] = PyArray_DescrFromType(dbf2np_map[i]); + assert(dbf2np[i]); + } +#endif + return 0; } @@ -240,3 +295,13 @@ void pyField_setup(PyObject *module) Py_INCREF(typeobj); PyModule_AddObject(module, "_Field", (PyObject*)&pyField_type); } + +void PyField_cleanup(void) +{ + size_t i; + + for(i=0; i<=DBF_ENUM; i++) { + Py_XDECREF(dbf2np[i]); + dbf2np[i] = NULL; + } +} diff --git a/devsupApp/src/dbrec.c b/devsupApp/src/dbrec.c index c267432..3fc6827 100644 --- a/devsupApp/src/dbrec.c +++ b/devsupApp/src/dbrec.c @@ -41,7 +41,7 @@ static int pyRecord_Init(pyRecord *self, PyObject *args, PyObject *kws) return -1; if(dbFindRecord(&self->entry, recname)){ - PyErr_SetString(PyExc_ValueError, "Record not found"); + PyErr_SetString(PyExc_ValueError, "No record by this name"); return -1; } return 0; @@ -175,7 +175,6 @@ int pyRecord_prepare(void) pyRecord_type.tp_init = (initproc)pyRecord_Init; pyRecord_type.tp_compare = (cmpfunc)pyRecord_compare; - pyRecord_type.tp_new = PyType_GenericNew; if(PyType_Ready(&pyRecord_type)<0) return -1; return 0; diff --git a/devsupApp/src/setup.c b/devsupApp/src/setup.c index eb97dea..ea73647 100644 --- a/devsupApp/src/setup.c +++ b/devsupApp/src/setup.c @@ -6,6 +6,9 @@ #undef _XOPEN_SOURCE #include +#ifdef HAVE_NUMPY +#include +#endif #include @@ -18,6 +21,13 @@ #include #include +int pyField_prepare(void); +void pyField_setup(PyObject *module); +void PyField_cleanup(void); + +int pyRecord_prepare(void); +void pyRecord_setup(PyObject *module); + /* dictionary of initHook names */ static PyObject *hooktable; @@ -62,6 +72,8 @@ static void cleanupPy(void *junk) PyEval_RestoreThread(state); + PyField_cleanup(); + /* release extra reference for hooktable */ Py_DECREF(hooktable); hooktable = NULL; @@ -176,20 +188,13 @@ static PyMethodDef devsup_methods[] = { {NULL, NULL, 0, NULL} }; -int pyField_prepare(void); -void pyField_setup(PyObject *module); - -int pyRecord_prepare(void); -void pyRecord_setup(PyObject *module); - /* initialize "magic" builtin module */ static void init_dbapi(void) { PyObject *mod, *hookdict, *pysuptable; pystate *st; - PyGILState_STATE state; - state = PyGILState_Ensure(); + import_array(); hooktable = PyDict_New(); if(!hooktable) @@ -221,7 +226,6 @@ static void init_dbapi(void) pyField_setup(mod); pyRecord_setup(mod); - PyGILState_Release(state); } #include @@ -240,11 +244,20 @@ static void fileRun(const iocshArgBuf *args){evalFilePy(args[0].sval);} static void pySetupReg(void) { + PyGILState_STATE state; + epicsThreadOnce(&setupPyOnceId, &setupPyOnce, NULL); iocshRegister(&codeDef, &codeRun); iocshRegister(&fileDef, &fileRun); initHookRegister(&pyhook); + + state = PyGILState_Ensure(); init_dbapi(); + if(PyErr_Occurred()) { + PyErr_Print(); + PyErr_Clear(); + } + PyGILState_Release(state); } #include