support numpy
This commit is contained in:
@ -4,12 +4,31 @@
|
|||||||
#undef _XOPEN_SOURCE
|
#undef _XOPEN_SOURCE
|
||||||
|
|
||||||
#include <Python.h>
|
#include <Python.h>
|
||||||
|
#ifdef HAVE_NUMPY
|
||||||
|
#include <numpy/ndarrayobject.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <epicsVersion.h>
|
#include <epicsVersion.h>
|
||||||
#include <dbCommon.h>
|
#include <dbCommon.h>
|
||||||
#include <dbAccess.h>
|
#include <dbAccess.h>
|
||||||
#include <dbStaticLib.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 {
|
typedef struct {
|
||||||
PyObject_HEAD
|
PyObject_HEAD
|
||||||
|
|
||||||
@ -152,6 +171,28 @@ static PyObject* pyField_putval(pyField *self, PyObject* args)
|
|||||||
Py_RETURN_NONE;
|
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[] = {
|
static PyMethodDef pyField_methods[] = {
|
||||||
{"name", (PyCFunction)pyField_name, METH_NOARGS,
|
{"name", (PyCFunction)pyField_name, METH_NOARGS,
|
||||||
"Return Names (\"record\",\"field\")"},
|
"Return Names (\"record\",\"field\")"},
|
||||||
@ -161,6 +202,8 @@ static PyMethodDef pyField_methods[] = {
|
|||||||
"Returns scalar version of field value"},
|
"Returns scalar version of field value"},
|
||||||
{"putval", (PyCFunction)pyField_putval, METH_VARARGS,
|
{"putval", (PyCFunction)pyField_putval, METH_VARARGS,
|
||||||
"Sets field value from a scalar"},
|
"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}
|
{NULL, NULL, 0, NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -222,6 +265,8 @@ static PyTypeObject pyField_type = {
|
|||||||
|
|
||||||
int pyField_prepare(void)
|
int pyField_prepare(void)
|
||||||
{
|
{
|
||||||
|
size_t i;
|
||||||
|
|
||||||
pyField_type.tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE;
|
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_flags |= Py_TPFLAGS_HAVE_GETCHARBUFFER|Py_TPFLAGS_HAVE_NEWBUFFER;
|
||||||
pyField_type.tp_methods = pyField_methods;
|
pyField_type.tp_methods = pyField_methods;
|
||||||
@ -231,6 +276,16 @@ int pyField_prepare(void)
|
|||||||
pyField_type.tp_new = PyType_GenericNew;
|
pyField_type.tp_new = PyType_GenericNew;
|
||||||
if(PyType_Ready(&pyField_type)<0)
|
if(PyType_Ready(&pyField_type)<0)
|
||||||
return -1;
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -240,3 +295,13 @@ void pyField_setup(PyObject *module)
|
|||||||
Py_INCREF(typeobj);
|
Py_INCREF(typeobj);
|
||||||
PyModule_AddObject(module, "_Field", (PyObject*)&pyField_type);
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -41,7 +41,7 @@ static int pyRecord_Init(pyRecord *self, PyObject *args, PyObject *kws)
|
|||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if(dbFindRecord(&self->entry, recname)){
|
if(dbFindRecord(&self->entry, recname)){
|
||||||
PyErr_SetString(PyExc_ValueError, "Record not found");
|
PyErr_SetString(PyExc_ValueError, "No record by this name");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@ -175,7 +175,6 @@ int pyRecord_prepare(void)
|
|||||||
pyRecord_type.tp_init = (initproc)pyRecord_Init;
|
pyRecord_type.tp_init = (initproc)pyRecord_Init;
|
||||||
pyRecord_type.tp_compare = (cmpfunc)pyRecord_compare;
|
pyRecord_type.tp_compare = (cmpfunc)pyRecord_compare;
|
||||||
|
|
||||||
pyRecord_type.tp_new = PyType_GenericNew;
|
|
||||||
if(PyType_Ready(&pyRecord_type)<0)
|
if(PyType_Ready(&pyRecord_type)<0)
|
||||||
return -1;
|
return -1;
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -6,6 +6,9 @@
|
|||||||
#undef _XOPEN_SOURCE
|
#undef _XOPEN_SOURCE
|
||||||
|
|
||||||
#include <Python.h>
|
#include <Python.h>
|
||||||
|
#ifdef HAVE_NUMPY
|
||||||
|
#include <numpy/ndarrayobject.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
@ -18,6 +21,13 @@
|
|||||||
#include <epicsThread.h>
|
#include <epicsThread.h>
|
||||||
#include <epicsExit.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 */
|
/* dictionary of initHook names */
|
||||||
static PyObject *hooktable;
|
static PyObject *hooktable;
|
||||||
|
|
||||||
@ -62,6 +72,8 @@ static void cleanupPy(void *junk)
|
|||||||
|
|
||||||
PyEval_RestoreThread(state);
|
PyEval_RestoreThread(state);
|
||||||
|
|
||||||
|
PyField_cleanup();
|
||||||
|
|
||||||
/* release extra reference for hooktable */
|
/* release extra reference for hooktable */
|
||||||
Py_DECREF(hooktable);
|
Py_DECREF(hooktable);
|
||||||
hooktable = NULL;
|
hooktable = NULL;
|
||||||
@ -176,20 +188,13 @@ static PyMethodDef devsup_methods[] = {
|
|||||||
{NULL, NULL, 0, NULL}
|
{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 */
|
/* initialize "magic" builtin module */
|
||||||
static void init_dbapi(void)
|
static void init_dbapi(void)
|
||||||
{
|
{
|
||||||
PyObject *mod, *hookdict, *pysuptable;
|
PyObject *mod, *hookdict, *pysuptable;
|
||||||
pystate *st;
|
pystate *st;
|
||||||
PyGILState_STATE state;
|
|
||||||
|
|
||||||
state = PyGILState_Ensure();
|
import_array();
|
||||||
|
|
||||||
hooktable = PyDict_New();
|
hooktable = PyDict_New();
|
||||||
if(!hooktable)
|
if(!hooktable)
|
||||||
@ -221,7 +226,6 @@ static void init_dbapi(void)
|
|||||||
pyField_setup(mod);
|
pyField_setup(mod);
|
||||||
pyRecord_setup(mod);
|
pyRecord_setup(mod);
|
||||||
|
|
||||||
PyGILState_Release(state);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#include <iocsh.h>
|
#include <iocsh.h>
|
||||||
@ -240,11 +244,20 @@ static void fileRun(const iocshArgBuf *args){evalFilePy(args[0].sval);}
|
|||||||
|
|
||||||
static void pySetupReg(void)
|
static void pySetupReg(void)
|
||||||
{
|
{
|
||||||
|
PyGILState_STATE state;
|
||||||
|
|
||||||
epicsThreadOnce(&setupPyOnceId, &setupPyOnce, NULL);
|
epicsThreadOnce(&setupPyOnceId, &setupPyOnce, NULL);
|
||||||
iocshRegister(&codeDef, &codeRun);
|
iocshRegister(&codeDef, &codeRun);
|
||||||
iocshRegister(&fileDef, &fileRun);
|
iocshRegister(&fileDef, &fileRun);
|
||||||
initHookRegister(&pyhook);
|
initHookRegister(&pyhook);
|
||||||
|
|
||||||
|
state = PyGILState_Ensure();
|
||||||
init_dbapi();
|
init_dbapi();
|
||||||
|
if(PyErr_Occurred()) {
|
||||||
|
PyErr_Print();
|
||||||
|
PyErr_Clear();
|
||||||
|
}
|
||||||
|
PyGILState_Release(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
#include <epicsExport.h>
|
#include <epicsExport.h>
|
||||||
|
Reference in New Issue
Block a user