====== Porting C Projects to IBM i ====== This document provides information on things you need to be aware when compiling C code which main target platform is not IBM i. ===== C Headers ===== The C Headers for most standard functions can be found at QSYSINC/H. ===== Compiler Directive ===== Probably some things will be configured and/or defined different on the IBM i platform as on other platforms. To differentiate between the OS types compile directives can be used. The IBM i platform automatically defines %%__OS400__%% which can be queried like this: #if __OS400__ // IBM i platform #else // other platforms #endif ===== Endian Type ===== Some C code takes advantage of the endian type of the system and because of that it needs to know on what type of system it runs on when it comes to byte order. There are little endian and big endian types. IBM i is a big endian type system. See Wikipedia article about [[https://en.wikipedia.org/wiki/Endianness | Endianness]]. ===== Include Files ===== Default include files (header files or copy books in RPG) are provided in the IFS at /QIBM/include ===== Data Types ===== There is an excellent paper about converting C prototypes and data types to its RPG equivalent from Barbara Morris, IBM: [[https://www.ibm.com/support/pages/converting-c-prototypes-rpg|Converting from C prototypes to RPG prototypes]] ==== Boolean ==== C does not come with many types like other languages and there is no type //bool// or //boolean//. But as there is the need for a boolean type in many libraries they defined **true** (equivalent to *ON in RPG) and **false** (equivalent to *OFF in RPG) in their code. #define true 1 #define false 0 IBM i provides these in their header file //stdbool.h// so you can include it like this #include ==== size_t ==== ''size_t'' is a type definition and resolved to an unsigned integer of 4-bytes on the IBM i platform. Thus you can declare it as follows dcl-s length uns(10); ===== Variable Number of Parameters ===== C supports variable number of parameters for functions. This feature can be used by calling the functions //va_arg, va_copy, va_start and va_end//. IBM only recently has completed this set of functions as //va_copy// was not available on any release prior to OS release version 7.2. See [[http://www.ibm.com/support/knowledgecenter/ssw_ibm_i_73/rtref/vaarg.htm | IBM Knowledge Center]]. ===== Structures and Pointers ===== The system will sometimes use more space for a structure than the space it is declared to use because the system will try to align it to a boundary 4, 8 or 16 bytes. If a pointer is part of the structure and the P128 Data Model is used then a pointer is 16 byte large and needs to be aligned on a 16 byte boundary. We are taking a string structure as an example: struct string { const char * value; size_t length; }; //size_t// resolves to a 4 byte integer type and a pointer (with the P128 data model) occupies 16 bytes of memory. This results in 20 bytes. But if we use the //sizeof// C function we see that 32 bytes are occupied by the structure. So in RPG we need to pad it with another 12 bytes. dcl-ds string qualified template; value pointer; length uns(10); dummy1 char(12); // to fill up the 16 byte to the next boundary end-ds; In RPG the built-in function //%size// can be used to see how many bytes a data structure occupies. These cases are not always covered with **ALIGN** keyword for a data structure. You might need to add some padding (by adding an additional dummy variable to fill up the space to the next boundary). From the //ILE C Language Reference//:
To allow proper alignment of components, holes or padding may appear between any consecutive members in the structure layout.
===== Bitwise Shift Operator ===== //<devel ibm rpg c}}