support numpy
This commit is contained in:
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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>
|
||||
|
Reference in New Issue
Block a user