support numpy

This commit is contained in:
Michael Davidsaver
2013-03-30 11:54:05 -04:00
parent 6c0abcb890
commit 22b05a22a9
3 changed files with 88 additions and 11 deletions

View File

@ -4,12 +4,31 @@
#undef _XOPEN_SOURCE
#include <Python.h>
#ifdef HAVE_NUMPY
#include <numpy/ndarrayobject.h>
#endif
#include <epicsVersion.h>
#include <dbCommon.h>
#include <dbAccess.h>
#include <dbStaticLib.h>
#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;
}
}

View File

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

View File

@ -6,6 +6,9 @@
#undef _XOPEN_SOURCE
#include <Python.h>
#ifdef HAVE_NUMPY
#include <numpy/ndarrayobject.h>
#endif
#include <stdio.h>
@ -18,6 +21,13 @@
#include <epicsThread.h>
#include <epicsExit.h>
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 <iocsh.h>
@ -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 <epicsExport.h>