The format of the name of each generated encode function is as follows:
asn1AvnEnc_[<prefix>]<prodName>
where <prodName>
is the name of the ASN.1 production for which the
function is being generated and <prefix>
is an optional prefix that can
be set via a configuration file setting. The configuration setting used to set the
prefix is the <typePrefix> element. This element specifies a prefix that will be
applied to all generated typedef names and function names for the production.
The calling sequence for each encode function is as follows:
ret = asn1AvnEnc_<name> (OSCTXT* pctxt, <name>* pvalue);
In this definition, <name>
denotes the prefixed production name
defined above.
The pctxt
argument is used to hold a context pointer to keep track of
encode parameters. This is a basic "handle" variable that is used to make the function
reentrant so it can be used in an asynchronous or threaded application. The user is
required to supply a pointer to a variable of this type declared somewhere in his or her
program. The variable should be initialized using the rtInitContext
run-time library function (see the C/C++ Common Run-Time Library Reference Manual for a complete description
of this function).
The pvalue
argument holds a pointer to the data to be encoded and is of
the type generated from the ASN.1 production.
The function result variable ret
returns 0 for success
or an error status code if encoding fails. Error status codes are defined in
rtsrc/asn1ErrCodes.h
and rtxsrc/rtxErrCodes.h
.
This section describes the step-by-step procedure for calling a C AVN encode function. This method must be used if C code generation was done. This method can also be used as an alternative to using the control class interface if C++ code generation was done.
Before any encode function can be called the user must first initialize an
encoding context. This is a variable of type OSCTXT. This variable holds all of the
working data used during the encoding 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 using the rtInitContext
function as
follows:
OSCTXT ctxt; if (rtInitContext (&ctxt) != 0) { /* initialization failed, could be a license problem */ printf (“context initialization failed (check license)\n”); return –1; }
The next step is set up the destination for the encoded message.
You specify a dynamic or static buffer by using rtxInitContextBuffer
,
or a stream by calling, e.g., rtxStreamFileCreateWriter
.
After initializing the context and populating a variable of the structure to be
encoded, an encode function can be called to encode the message. If the encoding is
successful and was done into a dynamic buffer, you can use rtxCtxtGetMsgPtr
to get a pointer to the message. Note that the buffer is not a null-terminated string.
If you want to treat the buffer as a null-terminated string, you can
write a null-terminator using rtxWriteBytes
.
A program fragment that could be used to encode an employee record is as follows:
#include employee.h /* include file generated by ASN1C */ int main () { int stat; OSCTXT ctxt; PersonnelRecord employee; /* typedef generated by ASN1C */ const char* filename = "message.txt"; /* Step 1: Initialize the context and create a file stream */ if (rtInitContext (&ctxt) != 0) { /* initialization failed, could be a license problem */ printf ("context initialization failed (check license)\n"); return –1; } stat = rtxStreamFileCreateWriter (&ctxt, filename); if (stat < 0) { printf ("Create file output stream failed\n"); rtxErrPrint (&ctxt); rtFreeContext (&ctxt); return stat; } /* Step 2: Populate the structure to be encoded */ employee.name.givenName = "SMITH"; ... /* Step 3: Call the generated encode function */ stat = asn1AvnEnc_PersonnelRecord (&ctxt, &employee); /* Step 4: Check the return status */ if (stat == 0) { printf ("Output file written successfully.\n"); } else { rtxErrPrint (&ctxt); return stat; } }
To encode to a static buffer, you simply pass the buffer and
its length to rtxInitContextBuffer
like so:
stat = rtxInitContextBuffer(pctxt, mybuf, mybuflen); if (stat != 0) /* Error! */
To encode to a dynamic buffer, pass a null buffer and 0 length to
rtxInitContextBuffer
:
stat = rtxInitContextBuffer(pctxt, 0, 0); if (stat != 0) /* Error! */
To encode to a stream, you must create a stream object within the context (OSCTXT). This object is an abstraction of the output device to which the data is to be encoded and is initialized by calling one of the following functions:
rtxStreamFileOpen
rtxStreamFileAttach
rtxStreamSocketAttach
rtxStreamMemoryCreate
rtxStreamMemoryAttach
The flags
parameter of these functions should
be set to the OSRTSTRMF_OUTPUT constant value to indicate an output stream is being
created (see the C/C++ Common Run-Time Library Reference
Manual for a full description of these functions).
It is also possible to use a simplified form of these function calls to create a writer interface to a file, memory, or socket stream (as in the previous example):
rtxStreamFileCreateWriter
rtxStreamMemoryCreateWriter
rtxStreamSocketCreateWriter
When you are finished encoding to a stream, close it by calling
rtxStreamClose