Exchanges between containers and standard C types

The integration engine runtime services library supplies the functions that collect values from the integration engine containers or fill them with values. Basically these functions translate handles into C-typed values in both directions (write/retrieve). A pair of function is available for each DML class.

The following table describes the matching between the class and the write and retrieve function names; the standard C type that corresponds to the class is also shown:

Class Retrieve function Write function C-Type












struct tm



char *



char *


Retrieve functions for scalar types (B, I, R and D classes) all follow the same signature model:

/* Scalar types retrieving functions */
int xibrt_getBoolean(xibrt_handle hCtx, xibrt_handle hSource);
long xibrt_getInteger(xibrt_handle hCtx, xibrt_handle hSource);
double xibrt_getFloat(xibrt_handle hCtx, xibrt_handle hSource);
struct tm xibrt_getDate(xibrt_handle hCtx, xibrt_handle hSource);

Retrieving strings or raw-data creates the problem of allocating enough room to receive a complete copy of the date read. A function is provided that returns the memory size (in bytes) needed to hold the retrieved data:

/* Retrieving memory sizes */
size_t xibrt_getSize(xibrt_handle hCtx, xibrt_handle hSource);

This function can be applied to any container and returns a size in bytes. The following table shows sizes returned by this call in several situations:

Platform Container
Function returns…

Sun Solaris



This platform considers 32-bit integers




32-bit windows encodes long integers on 32 bits

HP Itanium 64



This is a 64-bit platform that encodes integers on 8 bytes



The number of UTF8 bytes required to encode the text plus one.

The function never returns the characters length of the string because this logical size is useless for buffer allocation. One extra byte is reserved for \0 terminator.



The exact number of bytes held in the container

To retrieve a string from a container, you must first allocate a memory buffer large enough to hold the complete string. Then, you use xibrt_getString to clone the string held in the container into the buffer you supplied.

The following is a typical piece of code that extracts a string:

nBytes = xibrt_getSize(hCtx, hRegister);
pszString = calloc(nBytes, sizeof(char));
if (pszString != NULL && nBytes > strlen("change"))
   nCopiedBytes = xibrt_getString(hCtx, hRegister, nBytes, pszString);

Both string and raw-data retrieving functions use the same model as follows:

/* String and raw-data types retrieving functions */
size_t xibrt_getString(xibrt_handle hCtx, xibrt_handle hSource,
                       size_t nTargetSize, char *pszUTF8Target);
size_t xibrt_getBinary(xibrt_handle hCtx, xibrt_handle hSource,
                       size_t nTargetSize, char *pTarget);

In both cases, you supply the receive buffer address (pszTarget and pTarget) and its available size (nTargetSize). This size can be more or less than required. Bytes from source container are copied there until all available room is exhausted. This call cannot overflow. The actual count of copied bytes is then returned.

As the last argument name of xibrt_getString suggests, strings are always retrieved using UTF8 encoding. As a consequence, each call to xibrt_getString might trigger the character-set conversion engine. When designing your Custom Functions, be careful not to perform too many character-set conversions because this is a high time and resources consuming task.

Consider the following example. You want to design a DML Block that checks whether IBAN numbers from banking transactions are legal. If the IBAN is not valid, a question mark (?) is appended to that code while a plus (+) is added otherwise. You implement the check and modification in a C Custom Function, as follows:

/* Allocate buffer for modified IBAN */
nBytes = xibrt_getSize(hCtx, hIBAN);
pszIBAN = calloc(nBytes + 3, sizeof(char));

/* Collect the IBAN from its container */
xibrt_getString(hCtx, hRegister, nBytes, pszIBAN);
/* Check IBAN and append appropriate marker */
if (myIBANCheckRoutine(pszIBAN))
   /* IBAN is OK, append '+' */
   strcat(pszIBAN, "+");
   /* IBAN is KO, append '?' */
   strcat(pszIBAN, "?");
xibrt_setString(hCtx, hIBAN, nBytes + 1, pszIBAN);

This code can be very time consuming. If your IBAN strings are encoded, for example, in EBCDIC, the integration engine converts them twice:

  • From EBCDIC to UTF8 when the string is retrieved using xibrt_getString
  • From UTF8 back to EBCDIC when the string is given back to hIBAN using xibrt_setString.

The previous piece of code uses one of the write functions to places data into an existing container. As expected, writer functions for scalar types are natural:

/* Scalar types writing functions */
void xibrt_setBoolean(xibrt_handle hCtx,
                      int iSource, xibrt_handle hTarget);
void xibrt_setInteger(xibrt_handle hCtx,
                      long lSource, xibrt_handle hTarget);
void xibrt_setFloat(xibrt_handle hCtx,
                    double dSource, xibrt_handle hTarget);
void xibrt_setDate(xibrt_handle hCtx,
                   struct tm tSource, xibrt_handle hTarget);

Concerning writer functions for strings and raw-data, you must supply a buffer address and the length of significant data it contains, in bytes:

void xibrt_setString(xibrt_handle hCtx,
                    size_t nSourceSize, char*pszUTF8Source,
                    xibrt_handle hTarget);
void xibrt_setBinary(xibrt_handle hCtx,
                    size_t nSourceSize, char *pSource,
                    xibrt_handle hTarget);

After again, the system assumes the supplied string is UTF8 encoded.

The source length can be less than the actual source buffer size because only significant data (including final \0 for strings) is considered.

Related Links