The binding mechanism enables ADI class instances to map onto file system objects such as HDS components, or FITS arrays, extensions or keywords. The easiest way to understand is by way of an example. The Array class will be extended to handle HDS primitive arrays and FITS primary arrays.
The routine ADI uses to connect existing file system objects to an ADI class
is adi_fopen
, which looks like this,
adi_fopen( fspec, mode, class, id, status )where
fspec
is the path to the file object, mode
is the
access mode and class
is the ADI class we expect to open. For our
Array example we want something like,
adi_fopen( 'myfile.data_array', 'READ', 'Array', aid, status )ADI opens the object named in the first argument with access mode provided in the second, but is then stuck. It has to know how to connect the fact that it has a locator to a primitive HDS array to an ADI class instance. ADI has a concept of a "natural class" for a file object, ie. that ADI class which most closely matches the way the data is stored on disk. We can extend ADI's knowledge of these matches at run-time by defining a callback routine. A callback is simply a routine which is not executed immediately, but later when it is needed. The way this is done is,
external adi1_isarray adi_defrcb( 'HDS', 'Natural', adi1_isarray, status )The
adi_defrcb
routine defines a callback for a particular file
representation. The callback function must have one of the predefined
names listed in Appendix adi
and before the underscore. This flags it
as an internal routine, and the value indicates that it is HDS specific.
Callback routines have fixed argument lists and the definition for a
Natural
callback is the following,
<natural_callback>( id, class, status ) integer id character*(*) classThe
id
argument is the identifier of the File ADI has
connected to your named file. The purpose of the routine is to try and
derive a value for class
. Here is a pseudo-code version of
adi1_isarray
,
subroutine adi1_isarray( fid, class, status ) integer fid character*(*) class extract locator from FID use HDS routines DAT_PRIM and DAT_SHAPE to see if the object is a primitive array if it is, class = 'Array' else class = ' ' endADI now knows that the user has requested an Array and that it has a file object whose natural class is also Array Putting 2 and 2 togther ADI now has to create the instance of an Array class which has a binding to the File . This is done using another callback, but one which is specific to a particular class.
external ari1_open adi_defccb( 'Array%HDS', 'Open', ari1_open, status )The purpose of this routine is to write the values of the mandatory keywords into the empty Array instance. The syntax of the first argument tells ADI that this routine should only be applied to an Array object bound to an HDS based File .
subroutine ari1_open( fid, id, status ) integer fid,id extract locator from FID use DAT_SHAPE and DAT_TYPE to define the SHAPE and TYPE keywords endThere are two fundamntal ways of implementing file interface objects. The first and by far the simplest to program is imply to copy all the file data objects into memory on read, writing them out again if required. In reality this would be far too slow and use too much memory and a complex scheme which converts ADI accesses to the class instance object into file system access calls is required.
To make the mapping between the memory based Array object and the
file based HDS array useful we must now overload the the various
data access methods used by ADI. To simply read the values from a
class data member the adi_mget
routines are used, eg.
adi_mget1r( aid, 'Data', maxval, my_reals, nactval, status )The
adi_mget
routine is implemented by invoking the Get
method on the named class data member. This can be overloaded using
the callback mechanism,
adi_defccb( 'Array%HDS', 'Get(Data)', ari1_getdata, status ) subroutine ari1_getdata( id, mem_hdl, status ) integer id integer mem_hdl get locator from ID check data is valid get memory space TYPE, DIMS and PTR from MEMHDL DAT_GET the data to the address PTR end