Differences
This shows you the differences between two versions of the page.
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 | ||
+ | </ | ||
+ | |||
+ | ===== 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:// | ||
+ | |||
+ | ===== Include Files ===== | ||
+ | Default include files (header files or copy books in RPG) are provided in the IFS at | ||
+ | |||
+ | / | ||
+ | |||
+ | ===== Data Types ===== | ||
+ | There is an excellent paper about converting C prototypes and data types to its RPG equivalent from Barbara Morris, IBM: | ||
+ | |||
+ | [[https:// | ||
+ | |||
+ | |||
+ | ==== Boolean ==== | ||
+ | C does not come with many types like other languages and there is no type //bool// or // | ||
+ | |||
+ | #define true 1 | ||
+ | #define false 0 | ||
+ | |||
+ | IBM i provides these in their header file // | ||
+ | |||
+ | #include < | ||
+ | |||
+ | ==== size_t ==== | ||
+ | |||
+ | '' | ||
+ | |||
+ | 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:// | ||
+ | |||
+ | ===== 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; | ||
+ | }; | ||
+ | </ | ||
+ | |||
+ | //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; | ||
+ | </ | ||
+ | |||
+ | In RPG the built-in function //%size// can be used to see how many bytes a data structure occupies. | ||
+ | |||
+ | <note important> | ||
+ | |||
+ | <note tip>From the //ILE C Language Reference//: | ||
+ | |||
+ | ===== Bitwise Shift Operator ===== | ||
+ | //<<// | ||
+ | |||
+ | #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:// | ||
+ | |||
+ | ===== 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 '' | ||
+ | |||
+ | char sysname[] | ||
+ | char nodename[] name of this node within an implementation-dependent communications network | ||
+ | char release[] | ||
+ | char version[] | ||
+ | char machine[] | ||
+ | |||
+ | IBM i doesn' | ||
+ | |||
+ | See https:// | ||
+ | |||
+ | |||
+ | ===== Numbers declared as Hex ===== | ||
+ | C devs like to declare their numbers in hex instead of just writing the numbers. | ||
+ | |||
+ | #define UNQLITE_OPEN_CREATE | ||
+ | |||
+ | can be declared in RPG as | ||
+ | |||
+ | dcl-c UNQLITE_OPEN_CREATE 4; | ||
+ | |||
+ | And | ||
+ | |||
+ | #define UNQLITE_SYNC_FULL | ||
+ | |||
+ | can be declared in RPG as | ||
+ | |||
+ | dcl-c UNQLITE_SYNC_FULL 3; | ||
+ | |||
+ | |||
+ | ===== Contributors ===== | ||
+ | * Mihael Schmidt | ||
+ | |||
+ | |||
+ | {{tag> | ||
+ | |||