Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Previous revision
porting_c_projects_to_ibm_i [2018/08/28 11:55]
porting_c_projects_to_ibm_i [2021/04/27 08:45] (current)
mihael [Data Types]
Line 1: Line 1:
 +====== 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:
 +
 +<sxh c>
 +#if __OS400__
 +  // IBM i platform
 +#else
 +  // other platforms
 +#endif
 +</sxh> 
 +
 +===== 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 <stdbool.h>
 +
 +==== 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:
 +<sxh c>
 +struct string {
 +  const char * value;
 +  size_t length;
 +};
 +</sxh>
 +
 +//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.
 +
 +<sxh>
 +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;
 +</sxh>
 +
 +In RPG the built-in function //%size// can be used to see how many bytes a data structure occupies.
 +
 +<note important>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).</note>
 +
 +<note tip>From the //ILE C Language Reference//: <blockquote>To allow proper alignment of components, holes or padding may appear between any consecutive members in the structure layout.</blockquote></note>
 +
 +===== Bitwise Shift Operator =====
 +//<<// is the bitwise shift left operator which is often used to define constants like
 +
 +    #define MG_F_SEND_AND_CLOSE (1 << 10)
 +
 +In the example the symbol MG_F_SEND_AND_CLOSE has the value 1024. The following constant could be defined
 +
 +    dcl-c MG_FLAG_SEND_AND_CLOSE 1024;
 +
 +These constants are mostly used to be stacked into a single integer and the queried with bit operators like this
 +
 +    flags |= MG_F_SEND_AND_CLOSE;
 +    
 +    ...
 +    
 +    if (flags & MG_F_SEND_AND_CLOSE) {
 +        ...
 +    }
 +
 +The equivalent in RPG would be
 +
 +    flags = %bitor(flags : MG_F_SEND_AND_CLOSE);
 +    
 +    ...
 +    
 +    if (%bitand(flags : MG_F_SEND_AND_CLOSE) = MG_F_SEND_AND_CLOSE);
 +        ...
 +    endif;
 +
 +For more information on bitwise operators see [[https://en.wikipedia.org/wiki/Bitwise_operation | Bitwise Operation]] on Wikipedia.
 +
 +===== Pointer in Integers =====
 +In C you can do very tricky things but most of these things are not really compatible with most platform. Different platforms have f. e. different sizes for certain data types.
 +
 +One of those tricks is to store a pointer in an integer. This will work on 32-bit systems as a pointer is 4 byte and an integer also occupies 4 bytes.
 +
 +But on IBM i a pointer is 16 bytes (P128 data model) and an integer is just 4 bytes. This just won't work.
 +
 +===== uname / utsname =====
 +In the Unix world there is the function ''uname'' which returns a structure ''utsname'' which has at least the following members:
 +
 +    char  sysname[]  name of this implementation of the operating system
 +    char  nodename[] name of this node within an implementation-dependent communications network
 +    char  release[]  current release level of this implementation
 +    char  version[]  current version level of this release
 +    char  machine[]  name of the hardware type on which the system is running
 +
 +IBM i doesn't support this by itself.
 +
 +See https://pubs.opengroup.org/onlinepubs/7908799/xsh/sysutsname.h.html .
 +
 +
 +===== Numbers declared as Hex =====
 +C devs like to declare their numbers in hex instead of just writing the numbers.
 +
 +    #define UNQLITE_OPEN_CREATE           0x00000004
 +
 +can be declared in RPG as
 +
 +    dcl-c UNQLITE_OPEN_CREATE 4;
 +
 +And
 +
 +    #define UNQLITE_SYNC_FULL          0x00003
 +
 +can be declared in RPG as 
 +
 +    dcl-c UNQLITE_SYNC_FULL 3;
 +
 +
 +===== Contributors =====
 +  * Mihael Schmidt
 +
 +
 +{{tag>devel ibm rpg c}}
 +