|
|
(One intermediate revision by one other user not shown) |
Line 1: |
Line 1: |
| == EPICS: Code generated from DBD ==
| | Obsolete relpaced by "V4 Design: Runtime interfaces" |
| | |
| April 29 2005
| |
| | |
| | |
| == WARNING: This contains 1/2 baked ideas. Needs lots of work!!! ==
| |
| | |
| <center>
| |
| | |
| == Overview ==
| |
| | |
| </center>
| |
| | |
| This is the beginning of the task of deciding what code should be generated from the V4 database definition files. So far the following are discussed:
| |
| | |
| * code that implements a dataAccess interface.
| |
| * A header file for use by record support.
| |
| * Code that provides access without requiring the generated header file
| |
| * Code that provides a dataAccess interface.
| |
| | |
| The general scheme is to generate the following from each <tt>xxx.dbd</tt> file:
| |
| | |
| * <tt>xxx.h</tt>
| |
| This contains a <tt>struct</tt> definition that contains only data. The record support module uses this to access the record.
| |
| * <tt>xxxMeta.cpp</tt>
| |
| This implements an <tt>iocStructMetaSupport</tt>, which is described below, for accessing data without requiring the generated header file.
| |
| * <tt>xxxDA.h</tt>
| |
| This contains a <tt>class</tt> definition which is uses for dataAccess.
| |
| * <tt>xxxDA.cpp</tt>
| |
| This implements the dataAccess interface to xxx. All access from outside the record uses this interface to access the record.
| |
| | |
| The above files are generated for each <tt> struct</tt> and <tt>record</tt> definition.
| |
| | |
| ----
| |
| <center>
| |
| | |
| == Example Database Definition Files ==
| |
| | |
| </center>
| |
| | |
| The following Database Definition Files are used as examples.
| |
| | |
| * <tt>displayLimit.dbd</tt> contains:
| |
| struct(displayLimit) {
| |
| field(low,float64)
| |
| field(high,float64)
| |
| }
| |
| * <tt>exampleRecord.dbd</tt> contains:
| |
| include "dbCommon.dbd"
| |
| record(example) extends iocRecord {
| |
| field(value,float64)
| |
| field(displayLimit,struct(displayLimit))
| |
| }
| |
| * <tt>alltypesRecord.dbd</tt> contains:
| |
| include "dbCommon.dbd"
| |
| record(allTypes) extends iocRecord {
| |
| field(fbool,bool)
| |
| field(foctet,octet)
| |
| field(fint16,int16)
| |
| field(fuint16,uint16)
| |
| field(fint32,int32)
| |
| field(fuint32,uint32)
| |
| field(fint64,int64)
| |
| field(fuint64,uint64)
| |
| field(ffloat32,float32)
| |
| field(ffloat64,float64)
| |
| field(fstring,string)
| |
| field(fmenu,menu(menuName))
| |
| field(fenum,enum)
| |
| field(fstruct,struct(displayLimit))
| |
| field(flink,link(dir))
| |
| field(fdevice,device(dir,interfaceName))
| |
| }
| |
| | |
| ----
| |
| <center>
| |
| | |
| == iocTypes.h ==
| |
| | |
| </center>
| |
| | |
| File iocTypes.h describes the datatypes used by V4 databases:
| |
| | |
| <nowiki>/* TBD iocNdimArrayT*/
| |
| enum iocType {
| |
| iocUnknownT,iocBooleanT,iocOctetT,
| |
| iocInt16T,iocUInt16T,iocInt32T,iocUInt32T,iocInt64T,iocUInt64T,
| |
| iocFloat32T,iocFloat64T,
| |
| iocStringT,iocMenuT,iocEnumT,iocLinkT,iocDeviceT,iocArrayT
| |
| };
| |
| | |
| /* some of the following may require OSD definitions*/
| |
| typedef bool iocBoolean;
| |
| typedef char iocOctet;
| |
| typedef short iocInt16;
| |
| typedef unsigned short iocUInt16;
| |
| typedef int iocInt32;
| |
| typedef unsigned int iocUInt32;
| |
| typedef long long iocInt64;
| |
| typedef unsigned long long iocUInt64;
| |
| typedef float iocFloat32;
| |
| typedef double iocFloat64;
| |
| | |
| class iocRecord;
| |
| | |
| /* iocStructPtr always references a class that contains only data*/
| |
| typedef void * iocStructPtr;
| |
| | |
| /* iocInterfacePtr always references a class that contains only methods*/
| |
| typedef void *iocInterfacePtr;
| |
| | |
| class iocInterface {
| |
| const char *interfaceType;
| |
| iocInterfacePtr *pinterface;
| |
| };
| |
| | |
| /*iocString holds UTF-8 characters*/
| |
| class iocString {
| |
| public:
| |
| iocInt32 capacity; /*capacity in bytes*/
| |
| iocOctet *pstorage;
| |
| };
| |
| | |
| class iocStructMember {
| |
| iocString name;
| |
| iocType type;
| |
| };
| |
| | |
| class iocStructDef{
| |
| iocString name;
| |
| iocInt16 nmembers;
| |
| iocStructMember *pmember[];
| |
| iocInterface interface;
| |
| };
| |
| | |
| class iocStructField{
| |
| iocStructDef *piocStructDef;
| |
| iocStructPtr ptr;
| |
| };
| |
| | |
| class iocMenuDef{
| |
| public:
| |
| iocString name;
| |
| iocInt16 nchoices;
| |
| iocString *pchoice[];
| |
| };
| |
| | |
| class iocMenuField{
| |
| public:
| |
| iocInt16 index;
| |
| iocMenuDef *piocMenuDef[];
| |
| };
| |
| | |
| class iocEnumField{
| |
| public:
| |
| iocInt16 index;
| |
| iocInt16 nchoices;
| |
| iocString *pchoice[];
| |
| };
| |
| | |
| enum iocLinkDir {
| |
| iocLinkDirNone,
| |
| iocLinkDirForward,
| |
| iocLinkDirIn,
| |
| iocLinkDirOut,
| |
| iocLinkDirInOut
| |
| };
| |
| | |
| enum iocLinkType {
| |
| iocLinkTypeconstant,
| |
| iocLinkTypepvlink,
| |
| iocLinkTypecalink,
| |
| iocLinkTypedblink
| |
| };
| |
| | |
| class iocLinkDef{
| |
| public:
| |
| iocString choice;
| |
| iocLinkDir dir;
| |
| iocString configName;
| |
| iocString interfaceName;
| |
| iocInterface *piocInterface;
| |
| };
| |
| class iocLinkField{
| |
| public:
| |
| iocLinkType type;
| |
| iocLinkDef linkDef;
| |
| iocString pvname;
| |
| iocStruct config;
| |
| };
| |
| | |
| class iocDeviceDef {
| |
| public:
| |
| iocString choice;
| |
| iocLinkDir dir;
| |
| iocString configName;
| |
| iocInterface interface;
| |
| };
| |
| class iocDeviceField {
| |
| public:
| |
| iocDeviceDef device;
| |
| iocStruct config;
| |
| };
| |
| | |
| template< class ARR_T > class iocArray {
| |
| public:
| |
| iocInt32 capacity; /*capacity in number of elements*/
| |
| iocInt32 size; /*current number of elements*/
| |
| iocType type;
| |
| ARR_T *pstorage;
| |
| };
| |
| | |
| /* The following array types are supported by iocCore
| |
| * iocArray<void>;
| |
| * iocArray<iocOctet>;
| |
| * iocArray<iocInt16>;
| |
| * iocArray<iocUInt16>;
| |
| * iocArray<iocInt32>;
| |
| * iocArray<iocUInt32>;
| |
| * iocArray<iocInt64>;
| |
| * iocArray<iocUInt64>;
| |
| * iocArray<iocFloat32>;
| |
| * iocArray<iocFloat64>;
| |
| * iocArray<iocString>;
| |
| * iocArray<iocLinkField>;
| |
| **/
| |
| | |
| /* every struct and every record support module implements the following*/
| |
| class iocStructMetaSupport {
| |
| virtual iocStructPtr create() = 0;
| |
| virtual iocBoolean initialize(iocString *errorMessage, iocStructPtr ptr) = 0;
| |
| virtual iocBoolean finalize(iocString *errorMessage, iocStructPtr ptr) = 0;
| |
| virtual void destroy(iocStructPtr ptr) = 0;
| |
| virtual void *indexToAddr(iocString *errorMessage,
| |
| iocStructPtr ptr, iocInt16 index) = 0;
| |
| // ???? is anything else needed
| |
| };
| |
| | |
| /* record support implements the following*/
| |
| class iocRecordSupport {
| |
| virtual void special(iocRecord *piocRecord,
| |
| iocBoolean after,
| |
| iocInt16 nlevels, // number of elements in fieldIndex
| |
| iocInt16 fieldIndex[] // array of field indices
| |
| ) = 0;
| |
| };</nowiki>
| |
| | |
| ----
| |
| <center>
| |
| | |
| == Generated Record Support files ==
| |
| | |
| </center>
| |
| | |
| === displayLimit.dbd ===
| |
| | |
| From this file the following two files are generated for use by record support.
| |
| | |
| * File <tt>displayLimit.h</tt> contains:
| |
| class displayLimit {
| |
| public:
| |
| iocFloat64 low;
| |
| iocFloat64 high;
| |
| };
| |
| const iocInt16 displayLimit_low = 0;
| |
| const iocInt16 displayLimit_high = 1;
| |
| const iocInt16 displayLimit_lastIndex = displayLimit_high;
| |
| epicsExtern iocStructMetaSupport *pdisplayLimitMetaSupport;
| |
| * File <tt>displayLimitMeta.cpp</tt> contains:
| |
| class displayLimitMetaSupport : public iocStructMetaSupport
| |
| {
| |
| iocStructPtr create();
| |
| iocBoolean initialize(iocString *errorMessage, iocStructPtr ptr);
| |
| iocBoolean finalize(iocString *errorMessage, iocStructPtr ptr);
| |
| void destroy(iocStructPtr ptr);
| |
| void *indexToAddr(iocString *errorMessage,
| |
| iocStructPtr ptr, iocInt16 index);
| |
| }
| |
| iocStructMetaSupport *pdisplayLimitMetaSupport;
| |
| iocStructPtr displayLimitMetaSupport::create() {return new displayLimit;}
| |
| iocBoolean displayLimitMetaSupport::initialize(
| |
| iocString *errorMessage,iocStructPtr ptr)
| |
| {
| |
| displayLimit *pdisplayLimit = prt;
| |
| pdisplayLimit->low = 0;
| |
| pdisplayLimit->high = 0;
| |
| return iocTrue;
| |
| }
| |
| iocBoolean displayLimitMetaSupport::finalize(
| |
| iocString *errorMessage,iocStructPtr ptr)
| |
| { return iocTrue}
| |
| void displayLimitMetaSupport::destroy(iocStructPtr ptr) {delete ptr;}
| |
| void * displayLimitMetaSupport::indexToAddr(iocString *errorMessage,
| |
| iocStructPtr ptr, iocInt16 index)
| |
| {
| |
| displayLimit *pdisplayLimit = ptrptr;
| |
| switch(index) {
| |
| case displayLimit_low: return (void *)&pdisplayLimit->low;
| |
| case displayLimit_high: return (void *)&pdisplayLimit->high;
| |
| default: break;
| |
| }
| |
| // write a message to errorMessage How?
| |
| return null;
| |
| }
| |
| static void displayLimitRegister(void)
| |
| {
| |
| pdisplayLimitMetaSupport = new displayLimitMetaSupport;
| |
| // NOTE MUST ALSO register interface
| |
| }
| |
| epicsExportRegistrar(displayLimitRegister);
| |
| | |
| === exampleRecord.dbd ===
| |
| | |
| From this files the following two files are generatedp>
| |
| | |
| * File <tt>exampleRecord.h</tt> contains:
| |
| class exampleRecord : iocRecord {
| |
| public:
| |
| iocFloat64 value;
| |
| iocStruct displayLimit;
| |
| };
| |
| const iocInt16 exampleRecord_firstIndex = 1001
| |
| const iocInt16 exampleRecord_value = 1001;
| |
| const iocInt16 exampleRecord_displayLimit = 1002;
| |
| const iocInt16 exampleRecord_lastIndex = exampleRecord_displayLimit;
| |
| epicsExtern iocStructMetaSupport *pexampleRecordMetaSupport;
| |
| * File <tt>exampleRecordMeta.cpp</tt> contains:
| |
| class exampleRecordMetaSupport : public iocClassMetaSupport
| |
| {
| |
| iocStructPtr create();
| |
| iocBoolean init(iocString *errorMessage, iocStructPtr ptr);
| |
| void destroy(iocStructPtr ptr);
| |
| void *indexToAddr(iocString *errorMessage,
| |
| iocStructPtr ptr, iocInt16 index);
| |
| }
| |
| iocClassMetaSupport *pexampleRecordMetaSupport;
| |
| iocStructPtr exampleRecordMetaSupport::create() { return new exampleRecord}
| |
| iocBoolean exampleRecordMetaSupport::initialize(
| |
| iocString *errorMessage,iocStructPtr ptr)
| |
| {
| |
| exampleRecord *pexampleRecord = ptr;
| |
| if(piocRecordMetaSupport->initialize(errorMessage,pexampleRecord)==iocFalse)
| |
| return iocFalse;
| |
| pexampleRecord->value = 0;
| |
| return iocTrue;
| |
| }
| |
| iocBoolean exampleRecordMetaSupport::finalize(
| |
| iocString *errorMessage,iocStructPtr ptr)
| |
| {
| |
| exampleRecord *pexampleRecord = ptr;
| |
| if(piocRecordMetaSupport->finalize(errorMessage,pexampleRecord)==iocFalse)
| |
| return iocFalse;
| |
| pexampleRecord->value = 0;
| |
| return iocTrue;
| |
| }
| |
| void exampleRecordMetaSupport::destroy(iocStructPtr ptr)
| |
| {
| |
| // Most records have much more to do
| |
| delete ptr;
| |
| }
| |
| void * exampleRecordMetaSupport::indexToAddr(iocString *errorMessage,
| |
| iocStructPtr ptr, iocInt16 index)
| |
| {
| |
| exampleRecord *pexampleRecord = ptrptr;
| |
| switch(index) {
| |
| case exampleRecord_common:
| |
| return (void *)&pexampleRecord->common;
| |
| case exampleRecord_value:
| |
| return (void *)&pexampleRecord->value;
| |
| case exampleRecord_displayLimit:
| |
| return (void *)&pexampleRecord->displayLimit;
| |
| default: break;
| |
| }
| |
| // write a message to errorMessage How?
| |
| return null;
| |
| }
| |
| static void exampleRecordRegister(void)
| |
| {
| |
| pexampleRecordMetaSupport = new exampleRecordMetaSupport;
| |
| // NOTE MUST ALSO register interface
| |
| }
| |
| epicsExportRegistrar(exampleRecordRegister);
| |
| | |
| === alltypesRecord.dbd ===
| |
| | |
| As a last example alltypesRecord.h is generated as follows:
| |
| | |
| class allTypesRecord {
| |
| public:
| |
| iocRecord common;
| |
| iocBoolean fbool;
| |
| iocOctet foctet;
| |
| iocInt16 fint16;
| |
| iocUInt16 fuint16;
| |
| iocInt32 fint32;
| |
| iocUInt32 fuint32;
| |
| iocInt64 fint32;
| |
| iocUInt64 fuint32;
| |
| iocFloat32 ffloat32;
| |
| iocFloat64 ffloat64;
| |
| iocString fstring;
| |
| iocMenu fmenu;
| |
| iocEnum fenum
| |
| iocStruct fstruct;
| |
| iocLink flink;
| |
| iocDevice fdevice;
| |
| };
| |
| | |
| const iocInt16 allTypes_firstIndex = 1001001
| |
| const iocInt16 allTypes_fbool = 1001;
| |
| const iocInt16 allTypes_foctet = 1002;
| |
| const iocInt16 allTypes_fint16 = 1003;
| |
| const iocInt16 allTypes_fuint16 = 1004;
| |
| const iocInt16 allTypes_fint32 = 1005;
| |
| const iocInt16 allTypes_fuint32 = 1006;
| |
| const iocInt16 allTypes_fint64 = 1007;
| |
| const iocInt16 allTypes_fuint64 = 1008;
| |
| const iocInt16 allTypes_ffloat32 = 1009;
| |
| const iocInt16 allTypes_ffloatn64 = 10010;
| |
| const iocInt16 allTypes_ffstring = 10011;
| |
| const iocInt16 allTypes_fmenu = 10012;
| |
| const iocInt16 allTypes_fenum = 10013;
| |
| const iocInt16 allTypes_fstruct = 10014;
| |
| const iocInt16 allTypes_flink = 10015
| |
| const iocInt16 allTypes_fdevice = 10016
| |
| const iocInt16 allTypes_lastIndex = allTypes_fdevice;
| |
| | |
| epicsExtern iocStructMetaSupport *allTypesMetaSupport;
| |
| | |
| ----
| |
| <center>
| |
| | |
| == Generated dataAccess files ==
| |
| | |
| </center>
| |
| | |
| == displayLimitDA.h ==
| |
| | |
| From <tt>displayLimit.dbd</tt> files style="font-family: courier">displayLimitDA.hand <tt>displayLimitDA.cpp</tt> are generated.
| |
| | |
| * <tt>displayLimitDA.h</tt> contains:
| |
| #ifdef displayLimitDAH
| |
| #define displayLimitDAH
| |
| #include <displayLimit.h>
| |
| #include <dataAccess.h>
| |
| #include <daDataLocator.h>
| |
| using namespace da;
| |
| class displayLimitDA : public propertyCatalog {
| |
| public:
| |
| displayLimitDA(displayLimit *pdisplayLimit);
| |
| ~displayLimitDA();
| |
| void traverse (propertyViewer & ) const;
| |
| traverseModifyStatus traverse(propertyManipulator &);
| |
| bool find (const propertyId &, propertyViewer &) const;
| |
| displayLimitDA & operator = (const displayLimitDA &) const;
| |
| displayLimitDA & operator != (const displayLimitDA &) const;
| |
| displayLimitDA & operator = (const daData &);
| |
| private:
| |
| displayLimit *pdisplayLimit;
| |
| static bool init;
| |
| static locator < displayLimitDA > locate;
| |
| void lowReadBinder ( propertyViewer & ) const;
| |
| void lowWriteBinder ( propertyViewer & ) const;
| |
| void highReadBinder ( propertyViewer & ) const;
| |
| void highWriteBinder ( propertyViewer & ) const;
| |
| };
| |
| #endif //displayLimitDAH
| |
| * <tt>displayLimitDA.cpp</tt> implements the dataAccess interface.
| |
| #include "displayLimitDA.h"
| |
| #include <daPropertyId.h>
| |
| bool displayLimitDA::init = false;
| |
| locator < displayLimitDA > displayLimitDA::locate;
| |
| static const propertyId propertyDisplayLimit("displayLimit");
| |
| static const propertyId propertyLow("low");
| |
| static const propertyId propertyHigh("high");
| |
| void displayLimitDA::traverse ( propertyViewer & viewer ) const
| |
| {
| |
| viewer.reveal(propertyLow,low);
| |
| viewer.reveal(propertyHigh,high);
| |
| }
| |
| traverseModifyStatus displayLimitDA::traverse ( propertyManipulator & manipulator ) const
| |
| {
| |
| manipulator.reveal(propertyLow,low);
| |
| manipulator.reveal(propertyHigh,high);
| |
| return tmsSuccess;
| |
| }
| |
| displayLimitDA &displayLimitDA::find ( const propertyId &type, propertyViewer &adt ) const
| |
| {
| |
| return displayLimitDA::locate.callExportFunction ( *this, type, adt );
| |
| }
| |
| bool displayLimitDA::operator == ( const displayLimitDA & d ) const
| |
| {
| |
| equivStatus stat = equiv ( *this, d );
| |
| return equivStatusToBool ( stat );
| |
| }
| |
| displayLimitDA & displayLimitDA::operator = ( const displayLimitDA & d )
| |
| {
| |
| assignStatus stat = assign ( *this, d );
| |
| throwExceptionIfUnsuccessful ( stat );
| |
| return *this;
| |
| }
| |
| void displayLimitDA::lowReadBinder(propertyViewer &adt ) const
| |
| { adt.reveal(propertyLow,low); }
| |
| void displayLimitDA::lowWriteBinder(propertyManipulator &adt ) const
| |
| { adt.reveal(propertyLow,low); }
| |
| void displayLimitDA::highReadBinder(propertyViewer &adt ) const
| |
| { adt.reveal(propertyHigh,high); }
| |
| void displayLimitDA::highWriteBinder(propertyManipulator &adt ) const
| |
| { adt.reveal(propertyHigh,high); }
| |
| displayLimitDA::displayLimitDA(displayLimit *p) : pdisplayLimit(p)
| |
| {
| |
| if(init==false) {
| |
| locate.installExportFunction(propertyLow,&lowReadBinder);
| |
| locate.installExportFunction(propertyLow,&lowWriteBinder);
| |
| locate.installExportFunction(propertyHigh,&highReadBinder);
| |
| locate.installExportFunction(propertyHigh,&highWriteBinder);
| |
| init = true;
| |
| }
| |
| }
| |
| | |
| == exampleRecord ==
| |
| | |
| From <tt>exampleRecord.dbd</tt> The following files are generated
| |
| | |
| * exampleRecordDA.h contains:
| |
| #ifdef exampleRecordDAH
| |
| #define exampleRecordDAH
| |
| #include <dataAccess.h>
| |
| #include <daDataLocator.h>
| |
| using namespace da;
| |
| class exampleRecordDA : public propertyCatalog {
| |
| public:
| |
| exampleRecordDA(exampleRecord *pexampleRecord);
| |
| ~exampleRecordDA();
| |
| void traverse (propertyViewer & ) const;
| |
| traverseModifyStatus traverse(propertyManipulator &);
| |
| bool find (const propertyId &, propertyViewer &) const;
| |
| exampleRecordDA & operator = (const exampleRecordDA &) const;
| |
| exampleRecordDA & operator != (const exampleRecordDA &) const;
| |
| exampleRecordDA & operator = (const daData &);
| |
| private:
| |
| exampleRecord *pexampleRecord;
| |
| static bool init;
| |
| static locator < exampleRecordDA > locate;
| |
| void lowReadBinder ( propertyViewer & ) const;
| |
| void lowWriteBinder ( propertyViewer & ) const;
| |
| void highReadBinder ( propertyViewer & ) const;
| |
| void highWriteBinder ( propertyViewer & ) const;
| |
| };
| |
| #endif //exampleRecordDA
| |
| * <tt>exampleRecordDA.cpp</tt> is the dataAccess interface for exampleRecord
| |
| <nowiki> #include "exampleRecord.h"
| |
| #include <daPropertyId.h>
| |
| struct exampleRecordDAPvt {
| |
| displayLimitDA *pdisplayLimitDA;
| |
| };
| |
| bool exampleRecordDA::init = false;
| |
| locator < exampleRecordDA > exampleRecordDA::locate;
| |
| static const propertyId propertyValue("value");
| |
| static const propertyId propertyDisplayLimit("displayLimit");
| |
| void exampleRecordDA::traverse ( propertyViewer & viewer ) const
| |
| {
| |
| displayLimitDA *pdisplayLimitDA = pexampleRecordDAPvt->pdisplayLimitDA;
| |
| viewer.reveal(propertyValue,value);
| |
| pdisplayLimitDA->traverse(viewer);
| |
| }
| |
| traverseModifyStatus exampleRecordDA::traverse ( propertyManipulator & manipulator ) const
| |
| {
| |
| displayLimitDA *pdisplayLimitDA = (displayLimitDA*)recDAPvt;
| |
| manipulator.reveal(propertyValue,value);
| |
| return pdisplayLimitDA->traverse(manipulator);
| |
| }
| |
| exampleRecordDA &exampleRecordDA::find ( const propertyId &type, propertyViewer &adt ) const
| |
| {
| |
| return exampleRecordDA::locate.callExportFunction ( *this, type, adt );
| |
| }
| |
| bool exampleRecordDA::operator == ( const exampleRecordDA & d ) const
| |
| {
| |
| equivStatus stat = equiv ( *this, d );
| |
| return equivStatusToBool ( stat );
| |
| }
| |
| exampleRecordDA & exampleRecordDA::operator = ( const exampleRecordDA & d )
| |
| {
| |
| assignStatus stat = assign ( *this, d );
| |
| throwExceptionIfUnsuccessful ( stat );
| |
| return *this;
| |
| }
| |
| void exampleRecordDA::valueReadBinder(propertyViewer &adt ) const
| |
| { adt.reveal(propertyValue,value); }
| |
| void exampleRecordDA::valueWriteBinder(propertyManipulator &adt ) const
| |
| { adt.reveal(propertyValue,value); }
| |
| exampleRecordDA::exampleRecordDA(exampleRecord *p) : pexampleRecord(p)
| |
| {
| |
| if(init==false) {
| |
| locate.installExportFunction(propertyValue,&valueReadBinder);
| |
| locate.installExportFunction(propertyValue,&valueWriteBinder);
| |
| locate.installExportFunction(propertyDisplayLimit,&displayLimitReadBinder);
| |
| locate.installExportFunction(propertyDisplayLimit,&displayLimitWriteBinder);
| |
| init = true;
| |
| }
| |
| pexampleRecordDAPvt->pdisplayLimitDA = new displayLimitDA(pdisplayLimit);
| |
| }
| |
| </nowiki>
| |
| | |
| ----
| |
| <center>
| |
| | |
| == Standard Interfaces ==
| |
| | |
| </center>
| |
| | |
| NOTE: This discussion belongs elsewhere but for now it here.
| |
| | |
| <tt>iocTypes.h</tt> defines two interfaces:
| |
| | |
| * <tt>iocStructMetaSupport</tt>
| |
| * <tt>iocRecordSupport</tt>
| |
| | |
| This is the beginning of defining the successor to the V3 Record Support Entry Table. This needs more thought so the following are just preliminary ideas.
| |
| | |
| === <tt>iocStructMetaSupport</tt> ===
| |
| | |
| This has an implementation for every <tt>struct</tt> and every <tt>record</tt>. A tool will exist to create this support. For most structures the generated file may be sufficient. For a "smart" <tt>struct</tt> and for all record types the generated file is only a skeleton that must be modified to implement the semantics. It contains the following methods:
| |
| | |
| ; <tt>create</tt>
| |
| : Create storage for the <tt>struct</tt> or <tt>record</tt>. The default implementation should always be sufficiant.
| |
| ; <tt>initialize</tt>
| |
| : Perform initialization. This is analagous to V3 <tt>init_record</tt>.
| |
| : Questions. Are multiple passes needed? How many? Note that device link, device have separate interfaces for connecting and disconnecting.
| |
| ; <tt>finalize</tt>
| |
| : Is this needed? Are multiple passes needed?
| |
| ; <tt>destroy</tt>
| |
| : free storage used by <tt>struct</tt> or <tt>record</tt>
| |
| ; <tt>indexToAddr</tt>
| |
| : This converts a field index to an address. The generated header files contain the field indices.
| |
| ; Additional????
| |
| : Are they needed?
| |
| | |
| === <tt>iocRecordSupport</tt> ===
| |
| | |
| This is implemented by record support. Support for "smart" structures can also implement this interface. It implements the following methods:
| |
| | |
| ; <tt>special</tt>
| |
| : Called before and after the field is modified from outside record support itself. fieldIndex is an array in field indices that locate the exact field being modified.
| |
| ; Additional????
| |
| : Are they needed?
| |