diff options
Diffstat (limited to 'doc/html/UsingC.html')
-rw-r--r-- | doc/html/UsingC.html | 505 |
1 files changed, 505 insertions, 0 deletions
diff --git a/doc/html/UsingC.html b/doc/html/UsingC.html new file mode 100644 index 0000000..3acab85 --- /dev/null +++ b/doc/html/UsingC.html @@ -0,0 +1,505 @@ +<html> + <head> + <title>IEEEIO C Interface</title> + </head> + <body bgcolor="#F0F0F0"> + <table><tr> + <td><img src="Images/info.gif"></td> + <td><h1>ANSI and K&R C</h1></td> + </tr></table> + <hr> + <h1>Using the C Interface</h1> + To use the C interface, you must include the + headers <b>IO.h</b> and <b>IEEEIO.h</b>. By default the headers + are treated as K&R C (eg. no prototypes) because that is the + default of for many workstation C compilers. To enable the ANSI + C prototypes compile with -DANSI or use <b>#define ANSI</b> in + your source files before you include the <b>IO.h</b> and + <b>IEEEIO.h</b> headers. If you only require + the IEEEIO interface, you link only with <b>libieeeio.a</b> using + <code>-L$IEEE_DIRECTORY/lib -lieeeio</code><p> + + If you also want HDF support you must also include the header + <b>HDFIO.hh</b> and link with <b>libhdfio.a</b> and + the usual complement of HDF libraries using + <code>-L$HDF_DIRECTORY/lib -L$IEEE_DIRECTORY/lib -lhdfio -lieeeio -lmfhdf -ldf -ljpeg -lz</code><p> + + <hr> + <h1>C Subroutines</h1> + <UL> + <LI><a href="#Opening">Opening and Closing Datafiles</a> + <LI><a href="#Writing">Writing Datasets</a> + <LI><a href="#Reading">Reading Datasets</a> + <LI><a href="#Seeking">Random Access to Datasets + <i>(Seeking)</i></a> + <LI><a href="#WriteAttribs">Writing Attributes</a> + <LI><a href="#ReadAttribs">Reading Attributes</a> + <LI><a href="#WriteAnn">Writing Annotations</a> + <LI><a href="#ReadAnn">Reading Annotations</a> + <LI><a href="#ReadWriteChunk">Writing and Reading in Chunks</a> + </UL> + + <hr> + <a name="Opening"><h2>Opening</h2></a> + Just like the familiar <b>FILE*</b> type for C stdio operations, all + IEEEIO operations require a file handle. The type of this handle is + IOFile (and 8-byte integer number). The <b>IEEEopen()</b> and + <b>HDFIOopen()</b> + routines are used to create this handle and the IOclose() subroutine can + be used to close file handles of either type.<p> + <b>ANSI C Prototype</b><br> + <code>IOFile IEEEopen(char *filename,char *accessmode);</code><br> + <DL> + <DT><i>filename</i>: + <DD>The name of the IEEEIO data file to + open. The typical extension for these files is <i>.raw</i> + <DT><i>accessmode</i>: + <DD>The accessmode for the file. This is + one of 3 different access modes + <UL> + <LI><b>"read"</b>:<i>Opens a file in read-only mode. This + can also be selected using any of the standard fopen() + modes; "r" and "rb"</i> + <LI><b>"write"</b>:<i>Opens a file in write-only mode. If the + file does not exist, it will be created. If it does exist, it will be + truncated. This + can also be selected using any of the standard fopen() + modes; "w","wb","w+","w+b", and "wb+"</i> + <LI><b>"append"</b>: <i>Opens a file in read/write mode. The file + pointer is automatically placed at the end of the file for appending, + but random-access read operations are allowed as well.This + can also be selected using any of the standard fopen() + modes; "a","ab","a+","a+b", and "ab+"</i> + </UL> + </DL> + + After you open the file handle you can use the same set of + subroutines for operations on the file regardless of whether the + file is HDF or IEEEIO. The libraries manage all of this internally. So + the open step is the only thing that is important to differentiating + between your HDF and IEEEIO files. + There are plans, for example, to have a SocketIO system + that allows the data to be written out to a TCP socket instead of to a + file for real-time simulation-visualization systems. There are also + plans to use this interface to drive an existing Parallel IO + system.<p><br> + <pre> + /* write an IEEEIO file */ + IOFile writer = IEEEopen("datafileout.raw","write"); + /* write an HDF file */ + IOFile writer = HDFIOopen("datafileout.raw","w"); /* "w" is also valid */ + /* another way to open for writing */ + IOFile writer = IEEEopenWrite("datafileout.raw"); + /* open HDF file for reading */ + IOFile reader = HDFIOopen("datafilein.raw","read"); + /* another way to open an HDF file for reading */ + IOFile reader = HDFIOopenRead("datafileout.raw"); + /* another way to open an IEEEIO file for reading */ + IOFile reader = IEEEopenRead("datafileout.raw"); + </pre><p> + + You can test if the file was opened successfully using the + IOisValid() function.<br> + <pre> + IOFile fileID = IEEEopen("datafileout.raw","write"); + if(!IOisValid(fileID)) + puts("The file you specified does not exist or is not in a +readable format"); + </pre><br> + + To close the file, you simply use IOclose. + <pre> + IOclose(IOFile filehandle); + </pre> + + + <hr> + <a name="Writing"><h2>Writing</h2></a> + To write data you simply use the method write(). + <p><b>ANSI C Prototype</b><br> + <code>int IOwrite(IOFile filehandle,int numbertype,int rank,int + *dimensions,void *data);</code> + <DL> + <DT><i>filehandle</i> + <DD>An open filehandle for the datafile. + <DT><i>numbertype</i>: + <DD>The type of the data being stored + <i>(<a href="DataTypes.html">datatype definition</a>)</i>. + It can be one of + <UL> + <LI><b>FLOAT32</b><br><i>32-bit single-precision IEEE + float</i> + <LI><b>FLOAT64</b><br><i>64-bit double-precision IEEE + float</i> + <LI><b>STRING</b><br><i>Character string. This is + null-terminated automatically by the API. This is + interpreted differently from the <b>byte</b> datatype + which is raw data.</i> + <LI><b>INT8</b><br><i>byte</i> + <LI><b>INT16</b><br><i>16-bit short integer</i> + <LI><b>INT32</b><br><i>32-bit standard integer</i> + <LI><b>INT64</b><br><i>64-bit long integer. (note: this is not + availible on the Intel/Windows platform because it + does not allow 64-bit integers)</i> + <LI><b>UINT8</b><br><i>unsigned character</i> + <LI><b>UINT16</b><br><i>unsigned 16-bit short integer</i> + <LI><b>UINT32</b><br><i>unsigned 32-bit standard integer</i> + <LI><b>UINT64</b><br><i>unsigned 64-bit long + integer. (note: this is not availible on the + Intel/Windows platform)</i> + </UL> + <DT><i>rank</i> + <DD>Number of dimensions of the dataset + <DT><i>dimensions</i>: + <DD>An array of <i>rank</i> integers that give the dimensions of + the dataset + <DT><i>data</i>: + <DD>Your data array. + </DL> + + So to write a sample array of data. + <pre> + float myarray[40][50][60]; /* our bogus data array */ + int i,rank=3; + int dims[3]={60,50,40}; /* notice these are reversed. */ + /* this is because ieeeio assumes f77 order for data + and c/c++ use exactly the opposite ordering for data in */ +memory. + IOFile writer=IEEEopen("datafile.raw","write"); /* create a outfile */ + for(i=0;i<ndatasets;i++){ + . . . . computation . . . + IOwrite(writer,FLOAT32,rank,dims,myarray); /* write a dataset */ + . . . . you can write as many datasets as you want + } + IOclose(writer); /* then close the file */ + </pre> + + <hr> + <a name="Reading"><h2>Reading Data</h2></a> + Reading is a two step process. First you get information on + the size and type of the data you intend to read. This allows + you to allocate an array of the proper size and type for the + reading. Then you actually read the data into a pre-allocated + array. The methods for this are <b>IOreadInfo()</b> and + <b>IOread()</b>.<p> + <b>ANSI C Prototype</b><br> + <code>int IOreadInfo(IOFile filehandle,int *numbertype,int *rank,int + *dims,int maxdims);</code><p> + <DL> + <DT><i>filehandle</i> + <DD>A filehandle open for reading or appending. + <DT><i>numbertype</i>: + <DD>The type of the data being stored + <i>(<a href="DataTypes.html">datatype definition</a>)</i>. + It can be one of + <UL> + <LI><b>FLOAT32</b><br><i>32-bit single-precision IEEE float</i> + <LI><b>FLOAT64</b><br><i>64-bit double-precision IEEE float</i> + <LI><b>INT8</b><br><i>byte</i> + <LI><b>INT16</b><br><i>16-bit short integer</i> + <LI><b>INT32</b><br><i>32-bit standard integer</i> + <LI><b>INT64</b><br><i>64-bit long integer. (note: this is not + availible on the Intel/Windows platform)</i> + <LI><b>UINT8</b><br><i>unsigned character</i> + <LI><b>UINT16</b><br><i>unsigned 16-bit short integer</i> + <LI><b>UINT32</b><br><i>unsigned 32-bit standard integer</i> + <LI><b>UINT64</b><br><i>unsigned 64-bit long integer. (note: this is not availible on the Intel/Windows platform)</i> + </UL> + <DT><i>rank</i> + <DD>Number of dimensions of the dataset + <DT><i>dimensions</i>: + <DD>An array of <i>rank</i> integers that give the dimensions + of the dataset + <DT><i>maxdims</i>: + <DD>The maximum size of the dimensions array you given it. + This prevents array overruns if the dataset has more + dimensions than you were anticipating. It can be any positive + integer. + </DL> + This retrieves information about the datatype, rank, + and dimensions of the dataset to be retrieved. + By default the maximum size of the dimensions array is 3, + but you can set it to be larger.<p> + <b>ANSI C Prototype</b><br> + <code> + int IOread(IOFile filehandle,void *data); + </code><p> + This actually reads the dataset into the preallocated array + <i>data</i>.<p> + + Another useful utility function is IOsizeOf() which returns the + number of bytes in a give IO datatype in manner analogous to the + standard C sizeof() operator. + + So for instance, to read a simple dataset, you would do + <pre> + int rank; + int numbertype; + int dims[3]; + float *data; /* assumes float data */ + IOFile infile = IEEEopen("dataset.raw","read"); + IOreadInfo(infile,&numbertype,&rank,dims); + /* OK, we are assuming a 3D IO::Float32 array, + but you can be more sophisticated... */ + data = (float*)malloc(IOnBytes(numbertype,rank,dims)); + /* nBytes() is a convenience function... you could also use + data = (float*)malloc(dims[0] * dims[1] * dims[2] * IOsizeOf(numbertype)); */ + IOread(infile,data); /* read in the data */ + </pre><p> + + Since multiple datasets can be stored in a file, you can + retrieve them in the order they were written <i>(there is a <a + href="#Seeking">seek()</a> function that allows random access as + well)</i>. The method <b>readInfo()</b> implies reading the next + dataset stored in the file. The method <b>nDatasets()</b> tells how + many datasets are in a file. So typically if you want to read all + datasets in a file in order, you would use code similar to; + <pre> + IOFile infile = IEEEopen("dataset.raw","r"); + for(int i=0;i< IOnDatasets(infile);i++){ + .....lots of code.... + IOreadInfo(infile,&numbertype,&rank,dims); /* increments to next dataset */ + .....more code.... + } + </pre> + + <hr> + <a name="Seeking"><h2>Random Access to Datasets + <i>(Seeking)</i></h2></a> + You can select specific datasets in a file using the seek() + method.<p> + <b>ANSI C Prototype</b> + <code>int IOseek(IOFile filehandle,int index)</code> + <DL> + <DT><i>filehandle</i>: + <DD>Handle to a file open for reading. + <DT><i>index</i>: + <DD>The index of the dataset you want to read from. This can + be any number from 0 to (number_of_datasets - 1). + </DL> + + <hr> + <a name="WriteAttribs"><h2>Writing Attributes</h2></a> + Attributes allow you to attach extra information to each + dataset stored in the file. Each attribute has a name and an + array of data (of any of the standard IO datatypes) stored with + it. These attributes can be retrieved by name or by integer + index in the order in which they were stored. A typical + attribute would typically be parameters that describe the grid + or the data like, "origin" which would be the 3-vector of floats + which locates of the origin of a grid in 3-space. The method + used to write these attributes is <b>IOwriteAttribute()</b>.<p> + <b>ANSI C Prototype</b><br> + <code> + int IOwriteAttribute(IOFile filehandle,char *name,int numbertype,int + length,void *data) + </code><p> + <DL> + <DT><i>filehandle</i> + <DD>An open filehandle for the datafile. + <DT><i>name</i>: + <DD>Name of the attribute (like "origin" or "coordinates") + <DT><i>numbertype</i>: + <DD>The type of the data array associated with the attribute + <i>(<a href="DataTypes.html">datatype definition</a>)</i> + <DT><i>length</i>: + <DD>The number of elements in the data array. + <DT><i>data</i>: + <DD>The attribute data. + </DL><p> + So to write an attribute named <i>origin</i> along with a + 3-vector float for the coordinates of the origin, you would use; + <pre> + float origin[3]={5.1,0.3,0.5}; + /* and assuming the file is already open for writing + the following attribute will be attached to the last + written dataset. (you must have write data before adding + attribs) */ + IOwriteAttribute(writer,"origin",FLOAT32,3,origin); + </pre> + + <hr> + <a name="ReadAttribs"><h2>Reading Attributes</h2></a> + The attributes can be retrieved in the order they were written + or they can be retrieved by their name. To retrieve the + attributes in order, you would utilize the <b>IOnAttributes()</b> + method to determine how many attributes are attached, + <b>IOreadIndexedAttributeInfo()</b> to get the size and type of the + attribute based on its index (<i>use IOreadAttributeInfo() to get size + and type for the attribute based on its name</i>), + and <b>IOreadAttribute()</b> to read the attribute + data.<p> + <b>ANSI C Prototype</b><br> + <code>int IOnAttributes()</code><p> + <DL> + <DT><i>filehandle</i> + <DD>An open filehandle for the datafile. + <DT><i>returnvalue</i>: + <DD>Number of attributes in the file + </DL><p> + <b>ANSI C Prototype</b><br> + <code>int IOreadIndexedAttributeInfo(IOFile filehandle,int index,char *name,int *numbertype,int *length,int maxnamelength); + </code> + <DL> + <DT><i>filehandle</i> + <DD>An open filehandle for the datafile. + <DT><i>index</i>: + <DD>The index of the attribute which can be 0 to (nattributes-1) + <DT><i>name</i>: + <DD>A buffer in which the name of the attribute will be placed. + <DT><i>numbertype</i>: + <DD>The type of the attribute data + <i>(<a href="DataTypes.html">datatype definition</a>)</i> + <DT><i>length</i>: + <DD>The number of elements in the attribute data. + <DT><i>maxnamelength</i>:<DD>The maximum size of a name that can be + stored in the <b>name</b> buffer. It can be any positive integer. + </DL> + <p> + <b>ANSI C Prototype</b><br> + <code>int IOreadAttribute(IOFile filehandle,int index,void + *data);</code> + <DL> + <DT><i>filehandle</i> + <DD>An open filehandle for the datafile. + <DT><i>index</i>: + <DD>The index of the attribute data to read + <DT><i>data</i>: + <DD>The array into which the attribute data is copied. + </DL> + So for example, to read the attributes in order, you can use + <pre> + for(int i=0;i<IOnAttributes(infile);i++){ + char name[128]; + int length,datatype; + ... + IOreadIndexedAttributeInfo(infile,i,name,&datatype,&length,128); + ... allocate some data for storage + IOreadAttribute(infile,i,data); + } + </pre><p> + + The attributes can also be retrieve by name. In fact, the is + the most likely way you will use the attributes interface. The + <b>IOreadAttributeInfo()</b> method is overloaded to allow retrieval by + name as + well. It returns the index of the attribute if one is found with a + matching name: it returns -1 if one is not found. + <p><b>ANSI C Prototype</b><br> + <code> + int IOreadAttributeInfo(char *name,int *numbertype,int *length); + </code> + <DL> + <DT><i>filehandle</i> + <DD>An open filehandle for the datafile. + <DT><i>returnvalue</i>: + <DD>The index of the attribute if found or -1 if no attribute with + matching name is found. + <DT><i>name</i>: + <DD>The name of the attribute to find. + <DT><i>numbertype</i>: + <DD>Returns the numbertype of the stored attribute data + <i>(<a href="DataTypes.html">datatype definition</a>)</i> + <DT><i>length</i>: + <DD>he length of the stored attribute data. + </DL> + So a typical use of this interface would be to find an attribute + named "origin" and retrieve its data if it exists. + <pre> + int index = IOreadAttributeInfo(infile,"origin",&datatype,&length); + if(index>=0) /* the attribute exists */ + IOreadAttribute(infile,index,data); + else + puts("The attribute origin could not be found"); + </pre> + + </pre> + + <hr> + <a name="WriteAnn"><h2>Writing Annotations</h2></a> + An annotation is a text string which can be used to + describe a dataset. To write an annotation, you use the + writeAnnotation() method.<p> + <b>ANSI C Prototype</b><br> + <code> + int IOwriteAnnotation(IOFile filehandle,char *annotationtext) + </code> + <DL> + <DT><i>filehandle</i> + <DD>An open filehandle for the datafile. + <DT><i>annotationtext</i>: + <DD>A null terminated string of the annotation text + </DL> + The annotation will be attached to the last written dataset. + You can store more than one annotation per dataset and the + annotations can be of arbitrary length.<p> + + <hr> + <a name="ReadAnn"><h2>Reading Annotations</h2></a> + The annotations are stored in the order they are written. The + method <b>nAnnotations()</b> is used to find out how many + attributes are attached to a dataset. The method + <b>readAnnotationInfo()</b> is used to find the length of the + annotation and <b>readAnnotatin()</b> reads the actual + annotation text.<p> + <b>ANSI C Prototype</b><br> + <code> + int IOnAnnotations(IOFile filehandle); + </code> + <DL> + <DT><i>filehandle</i> + <DD>An open filehandle for the datafile. + <DT><i>returnvalue</i>: + <DD>Number of annotations attached to current dataset. + </DL><p> + <b>ANSI C Prototype</b><br><code> + IOreadAnnotationInfo(IOFile filehandle,int index,int *length) + </code> + <DL> + <DT><i>filehandle</i> + <DD>An open filehandle for the datafile. + <DT><i>index</i>: + <DD>Index of the annotations which can be 0 to (nannotations-1) + <DT><i>length</i>: + <DD>Length in characters of the annotation. This includes the + null-terminating character. + </DL> + <hr> + <a name="ReadWriteChunk"><h2>Writing and Reading in Chunks</h2></a> + For distributed-memory programming paradigms like HPF, MPI, or + PVM, it is often not unfeasible to write data to disk in a + single operation. For this reason, a <i>chunking</i> interface + is provided which allows you to write data in blocks to the + disk.<p> + To begin a chunk writing operation, you must first reserve a + data chunk in the file. This is accomplished using <b>IOreserveChunk()</b> + <b>ANSI C Prototype</b><br> + <code> + int IOreserveChunk(IOFile filehandle,int datatype,int rank,int *dims); + </code><p> + Once space has been allocated in the datafile, you can write + blocks of data specified by their dimensions and origin using + <b>IOwriteChunk()</b> + <b>ANSI C Prototype</b><br> + <code> + int IOwriteChunk(IOFile filehandle,int *dims,int *origin,void *data); + </code><p> + Likewise, it is possible to read chunks from the disk as + well. No special procedure is required to select a record to + read in chunks. Simply use <a href="#Reading">IOreadInfo()</a> + to get the dimensions and + type of the dataset and then use <b>IOreadChunk()</b> in place + of <b>IOread()</b> in order to read-in the data. + <b>ANSI C Prototype</b><br> + <code> + int IOreadChunk(IOFile filehandle,int *dims,int *origin,void *data); + </code><p> + <hr> + <address><a href="mailto:jshalf@suttung.aei-potsdam.mpg.de">John + Shalf</a></address> + <!-- Created: Mon Apr 7 12:52:52 MDT 1997 --> + <!-- hhmts start --> +Last modified: Thu Feb 4 21:58:57 CST 1999 +<!-- hhmts end --> + </body> +</html> |