Kurzurlaub - eine interessante Idee;-)
https://www.kurzurlaub.de... dort gibt es durchaus mal wieder Schnäppchen ;-)
... mal stöbern ...
... soooo schön ...
... mit meiner Isa ...
So ist nur einer!
... ein wahrer Traum ;-)
... soooo eine tolle Erfahrung!
return_type name ( parameters );For example
double fn (int p1, int p2); /* function "fn" with 2 4-byte integer */
/* parameters, returning 8-byte float */
Here is the matching RPG prototype D fn PR 8F EXTPROC('fn')
D p1 10I 0 VALUE
D p2 10I 0 VALUE
Note: C | RPG
------------------------+-----------------------------------
int x | D x 10I 0 VALUE
long x | D x 10I 0 VALUE
long long x | D x 20I 0 VALUE
unsigned int x | D x 10U 0 VALUE
unsigned long x | D x 10U 0 VALUE
unsigned long long x | D x 20U 0 VALUE
double x | D x 8F VALUE
|
short *x | D x 5I 0
int *x | D x 10I 0
long *x | D x 10I 0
long long *x | D x 20I 0
unsigned short *x | D x 5U 0
unsigned int *x | D x 10U 0
unsigned long *x | D x 10U 0
unsigned long long *x | D x 20U 0
float *x | D x 4F
double *x | D x 8F
char xA char passed by value is prototyped in RPG like this.
D x 1A VALUESee the section on C widening to see if you need to code your EXTPROC in a special way.
char *xA char passed by reference could map to a null-terminated string, or to an RPG character string passed by reference. See C string.
short s
unsigned short us
float f
The RPG parameter definition is coded similar to the way the parameter is code for these types passed by reference, but without the VALUE keyword. D s 5I 0 VALUE
D us 5U 0 VALUE
D f 4F VALUE
However, sometimes you may need to code *CWIDEN in your prototype. See C widening.wchar_t aThis is a double-byte character, most likely Unicode (RPG UCS-2 type), but it could be a specific CCSID, (RPG Graphic type).
D a nC VALUE
or
D a nG VALUE
Where "nC" and "nG" means a specific length, for example 25C, 100G etc.You may need to code your EXTPROC keyword in a special way for this parameter type. See the section on C widening.wchar_t *aThe RPG coding is the same as the coding for passing the parameter by value, but without the VALUE keyword.
D a nC
or
D a nG
struct SSS s;In the C include, there would be a definition for struct SSS. You first have to define a matching data structure template, SSS, for RPG.
D SSS DS QUALIFIED TEMPLATE
D ... subfields ...
Then, you can define the RPG parameter like this:D s VALUE LIKEDS(SSS)
struct SSS *s;This is similar to the case above, but since the parameter is passed by reference, you would omit the VALUE keyword in the RPG prototype.
D s LIKEDS(SSS)
TTT t;The RPG coding depends on how the TTT typedef is defined.
typedef double variance_t;
void fn(variance_t v);
When the typedef is for one of the scalar types, such as int, or float, then define a scalar template.D variance_t S 8F TEMPLATEThen define the RPG parameter using LIKE:
D fn PR EXTPROC('fn')
D v LIKE(variance_t) VALUE
typedef struct
{
int i;
double f;
} SSS;
Here is the matching RPG template D SSS DS TEMPLATE QUALIFIED ALIGN
D i 10I 0
D f 8F
Here is a C typedef for a union typedef union
{
int i;
double f;
} UUU;
Here is the matching RPG template D UUU DS TEMPLATE QUALIFIED
D i 10I 0 OVERLAY(TTT : 1)
D f 8F OVERLAY(TTT : 1)
Then define the RPG parameter using LIKEDS, and add the VALUE keyword since the struct or union is passed by value.D t LIKEDS(TTT) VALUE
TTT *t;The RPG coding is the same as the previous cases, except that the VALUE keyword is not used for the parameter.
D t LIKE(TTT)
or
D t LIKEDS(TTT)
void *pThe type of the parameter is not specified, so code the parameter as a pointer passed by value.
D p * VALUE
1. double sin ( double );
2. struct s
{
int i;
char c;
};
void fn ( float *a, struct s b, struct s *c, unsigned short *d);
D name PR EXTPROC(*CWIDEN : 'name').Use *CWIDEN for prototypes for functions written in C, and also for functions written in RPG, intended to be called by C.
int printf(const char *, ...);The first parameter is a null-terminated string indicating the value to be printed, with replacement variables indicated by %. For example,
printf("%s has %d contracts.", name, number);
says to substitute %s by the first parameter (name) and %d by the second parameter (number). Determining how to pass these parameters, and how to find out what the ellipsis means is beyond the scope of this article. For all functions that have ellipsis in the prototype, you must read the documentation for the function to find out what the optional parameters are.int fn (const int *i1, int *i2, int i3);The RPG equivalent:
D fn PR 10I 0 EXTPROC('fn')
D i1 10I 0 CONST
D i2 10I 0
D i3 10I 0 VALUE
typedef {type} XYZ;
For exampletypedef int XYZ;RPG coding
D XYZ_T S 10I 0 TEMPLATEThis could also be done in RPG as follows, by first defining a template for "int", and then defining another template for XYZ_T:
D int S 10i 0 TEMPLATE
...
D XYZ_T S LIKE(int) TEMPLATE
typedef {type} *XYZ;
For example typedef float *ABC_T;
typedef double* DEF_T;
typedef SOMETYPE * GHI_T;
Note that the position of the * doesn't matter in the C definition. D ABC_T S * TEMPLATE
D DEF_T S * TEMPLATE
D GHI_T S * TEMPLATE
Note that since RPG does not have typed pointers, all the RPG definitions are the same. typedef struct
{
type1 name1;
type2 name2;
...
} XYZ;
For example typedef struct
{
int i;
double d;
char name[10];
char c;
} S1_T;
typedef _Packed struct XYZ
{
int i;
double d;
char name[10];
char c;
} S2_T
RPG coding D S1_T DS ALIGN QUALIFIED TEMPLATE
D i 10i 0
D d 8f
D name 10a
D c 1a
D S2_T DS QUALIFIED TEMPLATE
D i 10i 0
D d 8f
D name 10a
D c 1a
Note: C structs default to having their subfields aligned. RPG data structures default to not having their subfields aligned. D regex_t DS 656 ALIGN QUALIFIED TEMPLATE
D etc
typedef union
{
type1 name1;
type2 name2;
...
} XYZ_t;
For example typedef union
{
int i;
double d;
char name[10];
char c;
} XYZ_t;
RPG coding D XYZ_t DS QUALIFIED TEMPLATE
D i 10i 0 overlay(XYZ:1)
D d 8f overlay(XYZ:1)
D name 10a overlay(XYZ:1)
D c 1a overlay(XYZ:1)
1. typedef int x1;
2. typedef struct
{
int i;
char c;
char x[15];
} x2;
3. typedef _Packed struct
{
int i[5];
double d;
} x3;
4. typedef union
{
short s;
float f;
double d[2];
} x4;
5. typedef x4 *x5;
void fn(void);you normally assume that the external name for this function is 'fn', so you normally code EXTPROC('fn').
#pragma map (fn, "fn_v2")
void fn(void);
The #pragma map says that the function named "fn" should actually be named "fn_v2" externally. enum QsyEimConnectSystem
{
QSY_EIM_CONFIG,
QSY_EIM_MASTER
};
Sometimes, the values for an enum are explicitly assigned. typedef enum AcctStatusEnum {
ACCOUNT_OPEN = 0,
ACCOUNT_LOCKED = 1,
ACCOUNT_EXPIRED = 2
} AcctStatusEnum;
Note:The only difference between "typedef enum" and "enum" is that the typedef is referred to by the name at the end of the definition, and the non-typedef is referred to by "enum name". For example, enum AcctStatusEnum above is referred to be the name following the "}" character, AcctStatusEnum. Enum CmpType is referred to be "Enum CmpType". typedef enum {
WLMPOL_ENC_UTF16 = 1,
WLMPOL_ENC_ASCII = 2,
WLMPOL_ENC_NATIVE = 3,
WLMPOL_ENC_UTF8 = 4
} WlmpolEncoding ;
Matching RPG named constants D WLMPOL_ENC_UTF16...
D C 1
D WLMPOL_ENC_ASCII...
D C 2
D WLMPOL_ENC_NATIVE...
D C 3
D WLMPOL_ENC_UTF8...
D C 4
#pragma enum(4)
or
#pragma enum(int)
means that the enums have type 4-byte integer.If you see the last value of the enum assigned a very large value, that will set the size of the enum to be an integer that can hold that value. In this case, the name of the final enum value indicates that the enum is intended to be an integer. typedef enum
{
Qpd_Call_Stack_Counter = 100,
Qpd_Suspected_Program = 101,
...
Qpd_Named_IFS_Object = 304,
Qpd_Service_Id = 400,
Qpd_Force_to_Integer = 70000
} Qpd_Key_t;
If you cannot determine the size of the enum, and you have access to the C compiler, write a program that includes the include file, that prints out the size of the enum.#includeIt prints "Size of AcctStatusEnum = 1", so you would code it as a 3i. If you have a parameter of type type, passed by value, you would probably need to code *CWIDEN for your prototype. See C widening.#include #include #include main() { printf ("Size of AcctStatusEnum = %d\n", sizeof(AcctStatusEnum)); }
#pragma enum(4)
...
enum QsyEimConnectSystem
{
QSY_EIM_CONFIG,
QSY_EIM_MASTER
};
RPG coding. Since it is not a typedef, I suggest that you add "enum_" to the template name. * QSYSINC/H QSYEIMAPI
* #pragma enum(4)
* enum QsyEimConnectSystem
* {
* QSY_EIM_CONFIG,
* QSY_EIM_MASTER
* };
D enum_QsyEinConnectSystem...
D S 10I 0 TEMPLATE
D QSY_EIM_CONFIG...
D C 0
D QSY_EIM_MASTER...
D C 1
typedef enum account_status {
ACCOUNT_OPEN = 0,
ACCOUNT_LOCKED = 1,
ACCOUNT_EXPIRED = 2
} account_status_t;
The RPG template uses the typedef name. * typedef enum account_status {
* ACCOUNT_OPEN = 0,
* ACCOUNT_LOCKED = 1,
* ACCOUNT_EXPIRED = 2
* } account_status_t;
D account_status_t...
D S 3I 0 TEMPLATE
D ACCOUNT_OPEN...
D C 0
D ACCOUNT_LOCKED...
D C 2
D ACCOUNT_EXPIRED...
D C 3
typedef _Packed struct Qp0l_Scan_Program_Data
{ /* */
char userProfile[10]; /* User profile */
Qp0l_Scan_Key_t scanKey; /* Scan key */
Qp0l_Scan_KeySign_t scanKeySignature;/* Scan key signature */
} Qp0l_Scan_Program_Data_t; /* */
Equivalent RPG coding * C struct definition is in QSYSINC/H QP0LSCAN
* typedef _Packed struct Qp0l_Scan_Program_Data
* {
* char userProfile[10];
* Qp0l_Scan_Key_t scanKey;
* Qp0l_Scan_KeySign_t scanKeySignature;
* } Qp0l_Scan_Program_Data_t;
D Qp0l_Scan_Program_Data_t...
D DS QUALIFIED TEMPLATE
D userProfile 10A
D scanKey LIKEDS(Qp0l_Scan_Key_t)
D scanKeySignature...
D LIKEDS(Qp0l_Scan_KeySign_t)
typedef struct
{
int i;
char a[10];
} TTT;
void fn (TTT *t);
Here is the RPG version of the "typedef" and the prototype with some example code calling the function D TTT DS ALIGN QUALIFIED
D TEMPLATE
D i 10I
D a 10A
D myTTT DS LIKEDS(TTT)
D fn PR EXTPROC(*CWIDEN : 'fn')
D t LIKEDS(TTT)
/free
myTTT.i = 25;
myTTT.a = "abcde";
fn (myTTT);
1. /*-----------------------------------------------------*/
/* fn1 */
/*-----------------------------------------------------*/
/* Required parameters: */
/* */
/* Input: p1: null-terminated string */
/* Input: p2: 10 bytes, right-adjusted, blank filled */
/* In: p3: 1-byte character */
/* */
/* Optional parameters: */
/* */
/* Input: p4: int */
/* Input: p5: int */
/* */
/* Returns: short int */
/*-----------------------------------------------------*/
short fn1 (char *p1, char *p2, char p3, ...)
2. /*-----------------------------------------------------*/
/* fn2 */
/*-----------------------------------------------------*/
/* Required parameters: */
/* */
/* Output: p1: integer */
/* Input: p2: array of integers */
/* Input: p3: array of pointers to character */
/* */
/* Returns: none */
/*-----------------------------------------------------*/
void fn2 (int *p1, int *p2, char *p3[]);
3. /*-----------------------------------------------------*/
/* num_recs */
/*-----------------------------------------------------*/
/* Required parameters: */
/* */
/* Input: filename: 10 bytes, blank-padded */
/* */
/* Returns: int */
/* */
/* Notes: */
/* 1. Compiling with DEFINE(DEBUG) will use a */
/* version of this function that outputs */
/* debugging information to stdout. */
/*-----------------------------------------------------*/
#ifdef DEBUG
#pragma map(num_recs, "num_recs_debug")
#endif
int num_recs (char filename[]);
1. double sin ( double );
D sin PR 8F EXTPROC('sin')
D 8F VALUE
2. struct s
{
int i;
char c;
};
void fn ( float *a, struct s b, struct s *c, unsigned short *d);
D s DS ALIGN QUALIFIED TEMPLATE
D i 10I
D c 1A
D fn PR EXTPROC('fn')
D a 4F
D b VALUE LIKEDS(s)
D c LIKEDS(s)
D d 5U 0
Note:EXTPROC(*CWIDEN:'fn') is also correct. 1. typedef int x1;
D x1 PR 10i 0
2. typedef struct
{
int i;
char c;
char x[15];
} x2;
D x2 DS ALIGN QUALIFIED TEMPLATE
D i 10I
D c 1A
D x 15A
3. typedef _Packed struct
{
int i[5];
double d;
} x3;
D x3 DS QUALIFIED TEMPLATE
D i 10I DIM(5)
D d 8F
4. typedef union
{
short s;
float f;
double d[2];
} x4;
D x4 DS QUALIFIED TEMPLATE
D s 5I DIM(5)
D f 4F
D d 8F DIM(2)
5. typedef x4 *x5;
D x5 S * TEMPLATE
/*-----------------------------------------------------*/
/* fn1 */
/*-----------------------------------------------------*/
/* Required parameters: */
/* */
/* Input: p1: null-terminated string */
/* Input: p2: 10 bytes, right-adjusted, blank filled */
/* In: p3: 1-byte character */
/* */
/* Optional parameters: */
/* */
/* Input: p4: int */
/* Input: p5: int */
/* */
/* Returns: short int */
/*-----------------------------------------------------*/
short fn1 (char *p1, char *p2, char p3, ...)
D fn1 PR 5I 0 EXTPROC(*CWIDEN1 : 'fn1')
D p1 * VALUE OPTIONS(*STRING) 2
D p2 10A OPTIONS(*RIGHTADJ) CONST 3
D p3 1A VALUE 4
D p4 10I 0 VALUE OPTIONS(*NOPASS) 5
D p5 10I 0 VALUE OPTIONS(*NOPASS)
Notes on the answer to question 1:fn1(file + '/' + lib : etc)
/*-----------------------------------------------------*/
/* fn2 */
/*-----------------------------------------------------*/
/* Required parameters: */
/* */
/* Output: p1: integer (dimension of the second parm) */
/* Input: p2: array of integers */
/* Input: p3: array of pointers to null-terminated */
/* strings. The final pointer must be */
/* null. */
/* Returns: none */
/*-----------------------------------------------------*/
void fn2 (int *p1, int *p2, char *p3[]);
D fn1 PR EXTPROC(*CWIDEN: 'fn2')
D p1 10I 0
D p2 10I 0 DIM(32767) 1
D CONST OPTIONS(*VARSIZE)
D p3 * DIM(32767)2
D OPTIONS(*VARSIZE)
Notes on the answer to question 2:[] * charyou get "array of pointer to character". Since RPG does not have typed pointers, you can only code "array of pointers" in RPG. And code some large number for the dimension, with OPTIONS(*VARSIZE), since you don't know the actual dimension of the array.
/*-----------------------------------------------------*/
/* num_recs */
/*-----------------------------------------------------*/
/* Required parameters: */
/* */
/* Input: filename: 10 bytes, blank-padded */
/* */
/* Returns: int */
/* */
/* Notes: */
/* 1. Compiling with DEFINE(DEBUG) will use a */
/* version of this function that outputs */
/* debugging information to stdout. */
/*-----------------------------------------------------*/
#ifdef DEBUG
#pragma map(num_recs, "num_recs_debug")
#endif
int num_recs (char filename[]);
There are two ways to handle conditionally picking up one name or the other: D num_recs PR
/IF DEFINED(DEBUG) 1
D EXTPROC(*CWIDEN : 'num_recs_debug')
/ELSE
D EXTPROC(*CWIDEN : 'num_recs')
/ENDIF
D filename 10A CONST
/IF DEFINED(DEBUG)
D num_recs_name...
D C 'num_recs_debug'
/ELSE
D num_recs_name...
D C 'num_recs'
/ENDIF
D num_recs PR EXTPROC(*CWIDEN : num_recs_name)
D filename 10A CONST
float f; x = fn (3, f, &x);(&x means the same as %addr(x) means in RPG)
void fn(char c);The obvious (but incorrect) RPG version is
When the RPG program calls the C function, the compiler will place the parameter in the first byte of the parameter area.D fn PR 8F EXTPROC('fn') D c 1A VALUE
callp fn('A')
+---+
Parameter area | A |
+---+
The C compiler will assume that the parameter has been widened, so it will expect a 4-byte integer, which it will convert to a 1-byte unsigned integer. +---+---+---+---+
Parameter area | A | x | y | z |
+---+---+---+---+
D fn PR 8F EXTPROC(*CWIDEN : 'fn')
D c 1A VALUE