start dset
This commit is contained in:
@ -39,6 +39,7 @@ devsup_SRCS_vxWorks += -nil-
|
||||
devsup_SRCS += setup.c
|
||||
devsup_SRCS += dbrec.c
|
||||
devsup_SRCS += dbfield.c
|
||||
devsup_SRCS += dbdset.c
|
||||
|
||||
# Add support from base/src/vxWorks if needed
|
||||
#devsup_OBJS_vxWorks += $(EPICS_BASE_BIN)/vxComLibrary
|
||||
|
218
devsupApp/src/dbdset.c
Normal file
218
devsupApp/src/dbdset.c
Normal file
@ -0,0 +1,218 @@
|
||||
|
||||
/* python has its own ideas about which version to support */
|
||||
#undef _POSIX_C_SOURCE
|
||||
#undef _XOPEN_SOURCE
|
||||
|
||||
#include <Python.h>
|
||||
|
||||
#include <epicsVersion.h>
|
||||
#include <assert.h>
|
||||
#include <dbCommon.h>
|
||||
#include <dbStaticLib.h>
|
||||
#include <dbAccess.h>
|
||||
#include <devSup.h>
|
||||
#include <dbLink.h>
|
||||
#include <recGbl.h>
|
||||
#include <alarm.h>
|
||||
#include <cantProceed.h>
|
||||
|
||||
typedef struct {
|
||||
dbCommon *precord;
|
||||
|
||||
DBLINK *plink;
|
||||
|
||||
PyObject *pyrecord;
|
||||
PyObject *support;
|
||||
} pyDevice;
|
||||
|
||||
static long parse_link(dbCommon *prec, const char* src)
|
||||
{
|
||||
PyObject *mod, *ret;
|
||||
pyDevice *priv = prec->dpvt;
|
||||
|
||||
mod = PyImport_ImportModule("devsup.db");
|
||||
if(!mod)
|
||||
return -1;
|
||||
|
||||
ret = PyObject_CallMethod(mod, "processLink", "ss", prec->name, src);
|
||||
Py_DECREF(mod);
|
||||
if(!ret)
|
||||
return -1;
|
||||
|
||||
if(!PyArg_ParseTuple(ret, "OO", &priv->pyrecord, &priv->support)) {
|
||||
Py_DECREF(ret);
|
||||
return -1;
|
||||
}
|
||||
|
||||
Py_INCREF(priv->pyrecord);
|
||||
Py_INCREF(priv->support);
|
||||
Py_DECREF(ret);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long detach_common(dbCommon *prec)
|
||||
{
|
||||
pyDevice *priv = prec->dpvt;
|
||||
PyObject *ret;
|
||||
|
||||
ret = PyObject_CallMethod(priv->support, "detach", "O", priv->pyrecord);
|
||||
Py_DECREF(priv->support);
|
||||
Py_DECREF(priv->pyrecord);
|
||||
priv->support = NULL;
|
||||
priv->pyrecord = NULL;
|
||||
if(!ret)
|
||||
return -1;
|
||||
Py_DECREF(ret);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long process_common(dbCommon *prec, int cause)
|
||||
{
|
||||
pyDevice *priv = prec->dpvt;
|
||||
PyObject *ret;
|
||||
|
||||
ret = PyObject_CallMethod(priv->support, "process", "Oi", priv->pyrecord, cause);
|
||||
if(!ret)
|
||||
return -1;
|
||||
Py_DECREF(ret);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long init_record(dbCommon *prec)
|
||||
{
|
||||
pyDevice *priv;
|
||||
DBENTRY ent;
|
||||
long ret;
|
||||
|
||||
priv = callocMustSucceed(1, sizeof(*priv), "init_record");
|
||||
|
||||
dbInitEntry(pdbbase, &ent);
|
||||
|
||||
/* find ourself */
|
||||
ret = dbFindRecord(&ent, prec->name);
|
||||
assert(ret==0); /* really shouldn't fail */
|
||||
|
||||
ret = dbFindField(&ent, "INP");
|
||||
|
||||
if(ret)
|
||||
ret = dbFindField(&ent, "OUT");
|
||||
|
||||
if(ret) {
|
||||
fprintf(stderr, "%s: Unable to find INP/OUT\n", prec->name);
|
||||
recGblSetSevr(prec, BAD_SUB_ALARM, INVALID_ALARM);
|
||||
free(priv);
|
||||
return 0;
|
||||
}
|
||||
|
||||
priv->plink = ent.pfield;
|
||||
|
||||
if(priv->plink->type != INST_IO) {
|
||||
fprintf(stderr, "%s: Has invalid link type %d\n", prec->name, priv->plink->type);
|
||||
free(priv);
|
||||
return 0;
|
||||
}
|
||||
|
||||
prec->dpvt = priv;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long init_record2(dbCommon *prec)
|
||||
{
|
||||
long ret = init_record(prec);
|
||||
if(ret==0)
|
||||
ret = 2;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static long add_record(dbCommon *prec)
|
||||
{
|
||||
pyDevice *priv = prec->dpvt;
|
||||
PyGILState_STATE pystate;
|
||||
long ret;
|
||||
|
||||
if(!priv)
|
||||
return 0;
|
||||
|
||||
pystate = PyGILState_Ensure();
|
||||
|
||||
if(parse_link(prec, priv->plink->value.instio.string)) {
|
||||
fprintf(stderr, "%s: Exception in add_record\n", prec->name);
|
||||
PyErr_Print();
|
||||
PyErr_Clear();
|
||||
ret = S_db_errArg;
|
||||
goto done;
|
||||
}
|
||||
assert(priv->support);
|
||||
ret = 0;
|
||||
done:
|
||||
PyGILState_Release(pystate);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static long del_record(dbCommon *prec)
|
||||
{
|
||||
pyDevice *priv = prec->dpvt;
|
||||
PyGILState_STATE pystate;
|
||||
|
||||
if(!priv)
|
||||
return 0;
|
||||
|
||||
pystate = PyGILState_Ensure();
|
||||
|
||||
if(detach_common(prec)) {
|
||||
fprintf(stderr, "%s: Exception in del_record", prec->name);
|
||||
PyErr_Print();
|
||||
PyErr_Clear();
|
||||
}
|
||||
|
||||
assert(!priv->support);
|
||||
|
||||
PyGILState_Release(pystate);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long process_record(dbCommon *prec)
|
||||
{
|
||||
pyDevice *priv = prec->dpvt;
|
||||
PyGILState_STATE pystate;
|
||||
|
||||
if(!priv || !priv->support)
|
||||
return 0;
|
||||
pystate = PyGILState_Ensure();
|
||||
|
||||
if(process_common(prec, 0)) {
|
||||
fprintf(stderr, "%s: Exception in process_record", prec->name);
|
||||
PyErr_Print();
|
||||
PyErr_Clear();
|
||||
}
|
||||
|
||||
assert(!priv->support);
|
||||
|
||||
PyGILState_Release(pystate);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static dsxt pydevsupExt = {&add_record, &del_record};
|
||||
|
||||
|
||||
static long init(int i)
|
||||
{
|
||||
if(i==0)
|
||||
devExtend(&pydevsupExt);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
typedef struct {
|
||||
dset com;
|
||||
DEVSUPFUN proc;
|
||||
} dset5;
|
||||
|
||||
static dset5 pydevsupCom = {{5, NULL, (DEVSUPFUN)&init, (DEVSUPFUN)&init_record, NULL}, (DEVSUPFUN)&process_record};
|
||||
static dset5 pydevsupCom2 = {{5, NULL, (DEVSUPFUN)&init, (DEVSUPFUN)&init_record2, NULL}, (DEVSUPFUN)&process_record};
|
||||
|
||||
#include <epicsExport.h>
|
||||
|
||||
epicsExportAddress(dset, pydevsupCom);
|
||||
epicsExportAddress(dset, pydevsupCom2);
|
@ -32,6 +32,19 @@ static int pyRecord_Init(pyRecord *self, PyObject *args, PyObject *kws)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pyRecord_compare(pyRecord *A, pyRecord *B)
|
||||
{
|
||||
dbCommon *a=A->entry.precnode->precord,
|
||||
*b=B->entry.precnode->precord;
|
||||
|
||||
if(a<b)
|
||||
return -1;
|
||||
else if(a==b)
|
||||
return 0;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
static PyObject* pyRecord_name(pyRecord *self)
|
||||
{
|
||||
dbCommon *prec=self->entry.precnode->precord;
|
||||
@ -145,6 +158,7 @@ int pyRecord_prepare(void)
|
||||
pyRecord_type.tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE;
|
||||
pyRecord_type.tp_methods = pyRecord_methods;
|
||||
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)
|
||||
|
@ -1 +1,11 @@
|
||||
registrar(pySetupReg)
|
||||
|
||||
device(longin, INST_IO, pydevsupCom, "Python Device")
|
||||
device(longout, INST_IO, pydevsupCom, "Python Device")
|
||||
|
||||
device(ai, INST_IO, pydevsupCom, "Python Device")
|
||||
device(ao, INST_IO, pydevsupCom, "Python Device")
|
||||
|
||||
device(ai, INST_IO, pydevsupCom2, "Raw Python Device")
|
||||
device(ao, INST_IO, pydevsupCom2, "Raw Python Device")
|
||||
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include <epicsThread.h>
|
||||
#include <epicsExit.h>
|
||||
|
||||
/* dictionary of initHook names */
|
||||
static PyObject *hooktable;
|
||||
|
||||
typedef struct {
|
||||
@ -184,7 +185,7 @@ void pyRecord_setup(PyObject *module);
|
||||
/* initialize "magic" builtin module */
|
||||
static void init_dbapi(void)
|
||||
{
|
||||
PyObject *mod, *hookdict;
|
||||
PyObject *mod, *hookdict, *pysuptable;
|
||||
pystate *st;
|
||||
PyGILState_STATE state;
|
||||
|
||||
@ -201,6 +202,11 @@ static void init_dbapi(void)
|
||||
|
||||
mod = Py_InitModule("_dbapi", devsup_methods);
|
||||
|
||||
pysuptable = PySet_New(NULL);
|
||||
if(!pysuptable)
|
||||
return;
|
||||
PyModule_AddObject(mod, "_supports", pysuptable);
|
||||
|
||||
hookdict = PyDict_New();
|
||||
if(!hookdict)
|
||||
return;
|
||||
@ -209,7 +215,7 @@ static void init_dbapi(void)
|
||||
for(st = statenames; st->name; st++) {
|
||||
PyDict_SetItemString(hookdict, st->name, PyInt_FromLong((long)st->state));
|
||||
}
|
||||
Py_INCREF(hooktable); /* an extra ref */
|
||||
Py_INCREF(hooktable); /* an extra ref for the global pointer */
|
||||
PyModule_AddObject(mod, "_hooktable", hooktable);
|
||||
|
||||
pyField_setup(mod);
|
||||
|
@ -52,3 +52,15 @@ class Field(_Field):
|
||||
|
||||
def __repr__(self):
|
||||
return 'Field("%s.%s")'%self.name()
|
||||
|
||||
def processLink(name, lstr):
|
||||
"""Process the INP or OUT link
|
||||
|
||||
Expects lstr to be "module arg1 arg2"
|
||||
|
||||
Returns (callable, Record, "arg1 arg2")
|
||||
"""
|
||||
rec = getRecord(name)
|
||||
modname, factname, args = lstr.split(None,2)
|
||||
mod = __import__(modname)
|
||||
return rec, mod.build(rec, args)
|
||||
|
Reference in New Issue
Block a user