How to take advantage of powerful builtin functions, APIs, and C library functions from RPG and Cobol -- even if...
you do not have the C compiler
By Ron Turull
This is an excerpt from an article that originally appeared in the June 2000 issue of Inside Version 4. It is provided courtesy of The 400 Group.
There are very powerful routines available on every AS/400 that is running V3 or later. They can be called from any ILE language, but they have remained relatively obscure because they are only documented in the ILE C language reference manuals or using C syntax notation. This is perfectly logical for one of the groups of routines -- the C library functions. But, for the other groups -- some APIs and the AS/400 builtin functions -- the logic seems to break down. (However, at the time when the AS/400 builtin functions were introduced, which was V2R3, it probably made more sense, since C was the only ILE language available and the builtin functions at that time were viewed by IBM as an extension to C.)
Nonetheless, most of these routines can be used by knowledgeable ILE RPG and ILE Cobol programmers to help solve difficult programming problems, use the full gamut of APIs, or just make a program "cleaner" or faster. Here are some examples of what these functions can do for you:
- The C library includes a dizzying array of string and memory manipulation functions, a number of date and time functions that augment the date/time APIs, a robust set of record I/O functions, and a fairly complete set of complex mathematical functions. One particularly handy function is memcpy, which copies a specified number of bytes from one variable (or memory location) to another variable (or memory location), without regard for data types. It should be noted that the term library here refers to the collection of C functions distributed with OS/400. This includes both the ANSI standard set of functions included with every C compiler regardless of platform, and the C/400 extended set of functions specific to the AS/400. The term library does not refer to an AS/400 library object of type *LIB.
- Some APIs, like the activate bound program API (QleActBndPgm), require a system pointer to an object. RPG has no intrinsic way of resolving (i.e., retrieving) a system pointer. But, both the C library and the AS/400 builtin functions contain routines for doing just that (and, in fact, they are called resolve system pointer); the C library contains the rslvsp function, while the builtin functions include the _RSLVSPx series of functions.
- The AS/400 builtin functions are, for the most part, encapsulations of MI instructions. They represent a risk-free interface to the MI instruction set -- a type of in-line assembler without the worry of IBM changing the underlying MI instructions.
- The CLI SQL APIs are examples of code that are not documented in C manuals, but the documentation for them is in C notation. Most of these APIs were ported from Unix or Unix-like boxes, where the main programming language is C. The common theme from IBM is that they were ported mainly to support the porting of third-party applications, which are mostly written in C and use the APIs, to the AS/400.
And, since these functions are approved, standard interfaces, you need not worry about the underlying architecture changing. For if it does, the function interface and operation will remain the same.
How is it possible?
There is no need for the C compiler here. All of the C functions are contained in five service programs in QSYS and are distributed with OS/400. The two service programs that contain the ANSI standard library functions are QC2UTIL1 and QC2UTIL2. The other three -- QC2IFS, QC2IO, and QC2SYS -- contain the IBM C/400 extended C functions (e.g., record I/0 functions that allow C programs to access files by record).
Don't worry about which service program contains the function you are calling, though. It's easiest to create a binding directory containing all five service programs and, then, just bind your program with the binding directory -- if a service program is not needed (i.e., your program does not call any of the procedures it contains), it is not bound into the resulting program.
Builtin functions are even easier, since they are "built-in" to the operating system. Actually, when a compiler encounters a call to a builtin function (the system maintains an internal list of all builtin functions), the compiler replaces the call with the actual machine instruction(s) the builtin function encapsulates. It's easier than calling an external program.