There are four steps to calling a compiler-generated C XML decode function:
Prepare a context variable for decoding;
Open a stream;
Call the appropriate compiler-generated decode function to decode the message;
Free the context after use of the decoded data is complete to free allocated memory structures
Before a C EXI decode function can be called; the user must initialize a context variable. This is a variable of type OSCTXT. This variable holds all of the working data used during the decoding of a message. The context variable is declared as a normal automatic variable within the top-level calling function. It must be initialized before use. This can be accomplished by calling the rtEXIInitContext function:
OSCTXT ctxt; // context variable stat = rtEXIInitContext (&ctxt); if (0 != stat) { printf ("Context initialization failed.\n"); rtxErrPrint (&ctxt); return stat; }
It is also possible to call the base context initialization function rtxInitContext followed by the rtEXIInitCtxtAppInfo to initialize the EXI subcontext. This can be useful if multiple encoding rules are used (for example, XML and EXI).
The next step is to create a stream object within the context. This object is an abstraction of the input device from which JSON data will be read and parsed. Calling one of the following functions initializes a stream for read operations:
rtxStreamFileCreateReader
rtxStreamMemoryCreateReader
rtxStreamSocketAttach
The flags parameter of the rtxStreamSocketAttach function should be set to the OSRTSTRMF_INPUT constant value to indicate an input stream is being created.
A decode function can then be called to decode the message. If the return status indicates success (0), then the message will have been decoded into the given XSD type variable. The decode function may automatically allocate dynamic memory to hold variable length items during the course of decoding. This memory will be tracked in the context structure, so the programmer does not need to worry about freeing it. It will be released when the context is freed.
The final step of the procedure is to close the stream and free the context block. The function to close the stream is rtxStreamClose . The function to free the context is rtxFreeContext.
A program fragment that could be used to decode a notebook record is as follows:
#include employee.h /* include file generated by XBinder */ main () { int stat; OSCTXT ctxt; notebook_ELEM pdu; const char* filename = "message.exi"; /* Step 1: Init context structure */ stat = rtEXIInitContext (&ctxt); if (0 != stat) { printf ("Context initialization failed.\n"); rtxErrPrint (&ctxt); return stat; } /* Note: no EXI header options are supported, so this must be set */ rtEXISetOption (&ctxt, OSEXI_NOHEADEROPTIONS); Init_notebook_ELEM (&ctxt, &pdu); /* Step 2: Open a stream reader */ stat = rtxStreamFileOpen (&ctxt, filename, OSRTSTRMF_INPUT); if (stat != 0) { rtxErrPrint (&ctxt); return -1; } /* Step 3: decode the record */ stat = EXIDec_notebook (&ctxt, &pdu); if (stat == 0) { if (trace) { printf ("Decode of Notebook was successful\n"); printf ("Decoded record:\n"); Print_notebook_ELEM ("notebook", &pdu); } } else { printf ("decode failed:\n"); rtxErrPrint (&ctxt); rtxStreamClose (&ctxt); return -1; } /* Step 4: Close the stream and free the context. */ rtxStreamClose (&ctxt); rtxFreeContext (&ctxt); return 0; }