ILE C/C++ Programmer's Guide

ILE-OPM CL Example: Calling OPM, COBOL, and RPG Programs from an ILE C++ Program

This program demonstrates some typical steps in creating a program that uses several ILE and OPM programming languages.

Program Description

The program is a small transaction-processing program that takes as input the item name, price, and quantity for one or more products. As output, the program displays the total cost of the items specified on the display and writes an audit trail of the transactions to a file.

Figure 270 shows the basic flow of the program.

Figure 270. ILE-OPM CL Example: Basic Program Structure



ilec3

Program Structure

The program consists of these components:

Program Activation

The ILE C++ program T2123IC5 is created with the CRTPGM default for the ACTGRP parameter, ACTGRP(*NEW). When the CL program calls the ILE C++ program, a new activation group is started.

The OPM CL, COBOL, and RPG programs are activated within the OPM default activation group.

Figure 271 shows the structure of this program in ILE.

Figure 271. Structure of the Program in ILE C++



ilec4

Program Files

The source code for each of the files that compose this program are an externally described file, a CL program, a CL command prompt, a C++ source file, and OPM COBOL program and an OPM RPG program.

Externally Described File T2123DD2

The file T2123DD2 contains the audit trail for the C++ program T2123IC5. The DDS source defines the fields for the audit file:

  R T2123DD2R
    USER          10          COLHDG('User')
    ITEM          20          COLHDG('Item name')
    PRICE         10S 2       COLHDG('Unit price')
    QTY            4S         COLHDG('Number of items')
    TXRATE         2S 2       COLHDG('Current tax rate')
    TOTAL         21          COLHDG('Total cost')
    DATE           6          COLHDG('Transaction date')
  K USER

CL Program T2123CL2

The CL program T2123CL2 passes the CL variables item_name, price, quantity and user_id by reference to an ILE C++ program T2123IC5.

PGM        PARM(&ITEMIN &PRICE &QUANTITY)
     DCL        VAR(&USER) TYPE(*CHAR) LEN(10)
     DCL        VAR(&USEROUT) TYPE(*CHAR) LEN(11)
     DCL        VAR(&ITEMIN)    TYPE(*CHAR) LEN(20)
     DCL        VAR(&ITEMOUT)   TYPE(*CHAR) LEN(21)
     DCL        VAR(&PRICE)     TYPE(*DEC)  LEN(10 2)
     DCL        VAR(&QUANTITY)  TYPE(*DEC)  LEN(2 0)
     DCL        VAR(&NULL)      TYPE(*CHAR) LEN(1) VALUE(X'00')
  /* ADD NULL TERMINATOR FOR THE ILE C PROGRAM                 */
     CHGVAR     VAR(&ITEMOUT) VALUE(&ITEMIN *TCAT &NULL)
     CHGVAR     VAR(&USEROUT) VALUE(&USER *TCAT &NULL)
  /* GET THE USERID FOR THE AUDIT FILE                         */
     RTVJOBA    USER(&USER)
  /* ENSURE AUDIT RECORDS WRITTEN TO CORRECT AUDIT FILE MEMBER */
     OVRDBF     FILE(T2123DD2) TOFILE(*LIBL/T2123DD2) +
                  MBR(T2123DD2) OVRSCOPE(*CALLLVL) SHARE(*NO)
     CALL       PGM(T2123IC5) PARM(&ITEMOUT &PRICE &QUANTITY +
                  &USEROUT)
     DLTOVR     FILE(*ALL)
ENDPGM

The Retrieve Job Attributes (RTVJOBA) command obtains the user ID for the audit trail. Arguments are passed by reference. They can be changed by the receiving ILE C++ program. The variables containing the user and item names are explicitly null-terminated in the CL program.

Notes:

  1. CL variables and numeric literals are not passed to an ILE C++ program with null-terminated strings.

  2. Character literals and logical literals are passed as null-terminated strings but are not widened with blanks.

  3. Numeric literals such as packed decimals are passed as 15,5 (8 bytes). Floating point constants are passed as double precision floating point values (1.2E+15).

  4. To pass parameters to an ILE program when you run it, use the PARM option of the CL Call (CALL) command.

CL Command Prompt T2123CM2

You use the CL command prompt T2123CM2 to prompt the user to enter item names, prices, and quantities that will be used by the C++ program T2123IC5.

CMD        PROMPT('CALCULATE TOTAL COST')
PARM       KWD(ITEM) TYPE(*CHAR) LEN(20) RSTD(*NO) +
             MIN(1) ALWUNPRT(*NO) PROMPT('Item name' 1)
PARM       KWD(PRICE) TYPE(*DEC) LEN(10 2) RSTD(*NO) +
             RANGE(0.01 99999999.99) MIN(1) +
             ALWUNPRT(*YES) PROMPT('Unit price' 2)
PARM       KWD(QUANTITY) TYPE(*INT2) RSTD(*NO) RANGE(1 +
             9999) MIN(1) ALWUNPRT(*YES) +
             PROMPT('Number of items' 3)

C++ Source File T2123IC5

The C++ source file T2123IC5 contains a main() function which receives the incoming arguments from the CL program T2123CL2. These arguments have been verified by the CL command prompt T2123CM2 and null-terminated within the CL program T2123CL2. All the incoming arguments are pointers.

The main() function calls the function CalcAndFormat() which is mapped to a COBOL name. It passes the price, quantity, taxrate, formatted_cost, and a success_flag to the OPM COBOL program T2123CB1 using the extern "OS nowiden" linkage specification, because the OPM COBOL program is not expecting widened parameters.

The formatted_cost and the success_flag values are updated in the C++ program T2123IC5.

If CalcAndFormat() returns successfully, a record is written to the audit trail by WriteAuditTrail() in the OPM RPG program.

The main() function in program T2123IC5 calls WriteAuditTrail() which is mapped to an RPG program name, and passes the user_id, item_name, price, quantity, taxrate, and formatted_cost, using the extern "OS" linkage specification.

Note:
By default, the compiler converts a short integer to an integer unless the nowiden parameter is specified on the extern linkage specification. The short integer in the C++ program is converted to an integer, and then passed to the OPM RPG program. The RPG program is expecting a 4-byte integer for the quantity variable. See Appendix B, Interlanguage Data-Type Compatibilities for information on data-type compatibility.
// This program is called by a CL program that passes an item
// name, price, quantity and user ID.
// COBOL is called to calculate and format the total cost.
// RPG is called to write an audit trail.
 
#include <iostream.h>
#include <stdlib.h>
#include <string.h>
#include <bcd.h>
 
// The #pragma map directive maps a new program name to the existing
// program name so that the purpose of the program is clear.
// Tell the compiler that there are dynamic program calls so
// arguments are passed by value-reference.
 
extern "OS nowiden" void CalcAndFormat(_DecimalT <10,2>,
                    short int, _DecimalT<2,2>, char[],
                    char *);
 
#pragma map(CalcAndFormat,"T2123CB1")
 
extern "OS" void WriteAuditTrail(char[], char[]      ,
                                 _DecimalT<10,2>, short int,
                                 _DecimalT<2,2>, char[]);
 
#pragma map(WriteAuditTrail,"T2123RP1")
 
int main(int argc, char *argv[])
{
// Incoming arguments from a CL program have been verified by
// the *CMD and null-terminated within the CL program.
// Incoming arguments are passed by reference from a CL program.
 
  char               *user_id;
  char               *item_name;
  short int          quantity;
  _DecimalT <10, 2>  price;
  _DecimalT <2,2>    taxrate = __D(".15");
  char               formatted_cost[22];
 
// Remove null terminator for RPG program. Item name is null
// terminated for C++.
 
   char             rpg_item_name[20];
   char             null_formatted_cost[22];
   char             success_flag = 'N';
   int              i;
 
 // Incoming arguments are all pointers.
 
   item_name =                        argv[1];
   price     = *((_DecimalT<10, 2> *) argv[2]);
   quantity  = *((short *)            argv[3]);
   user_id   =                        argv[4];
 
// Call the COBOL program to do the calculation, and return a
// Y/N flag, and a formatted result.
 
  CalcAndFormat(price, quantity, taxrate, formatted_cost,
                &success_flag);
 
  memcpy(null_formatted_cost,formatted_cost,sizeof(formatted_cost));
 
// Null terminate the result.
 
  formatted_cost[21] = '\0';
  if (success_flag == 'Y')
  {
    for (i=0; i<20; i++)
    {
 
// Remove null terminator for the RPG program.
 
      if (*(item_name+i) == '\0')
      {
        rpg_item_name[i] = ' ';
      }
      else
      {
        rpg_item_name[i] = *(item_name+i);
      }
    }
 
// Call an RPG program to write audit records.
 
    WriteAuditTrail(user_id, rpg_item_name, price, quantity,
                      taxrate, formatted_cost);
 
    cout <<quantity <<item_name << "plus tax ="
         <<null_formatted_cost <<endl;
  }
  else
  {
    cout <<"Calculation failed" <<endl;
  }
}

OPM COBOL Program T2123CB1

The OPM COBOL program T2123CB1 receives pointers to the values of the variables price, quantity and taxrate, and pointers to formatted_cost and success_flag.

The CalcAndFormat() function in program T2123CB1 calculates and formats the total cost. Parameters are passed from the ILE C++ program to the OPM COBOL program to do the tax calculation.

 IDENTIFICATION DIVISION.
 PROGRAM-ID. T2123CB1.
******************************************************
* parameters:                                        *
*   incoming:  PRICE, QUANTITY                       *
*   returns :  TOTAL-COST (PRICE*QUANTITY*1.TAXRATE) *
*              SUCCESS-FLAG.                         *
******************************************************
 ENVIRONMENT DIVISION.                                                         0
  CONFIGURATION SECTION.                                                       0
   SOURCE-COMPUTER. IBM-ISERIES.                                                    0
   OBJECT-COMPUTER. IBM-ISERIES.                                                    0
 DATA DIVISION.                                                                0
 WORKING-STORAGE SECTION.
 
        01  WS-TOTAL-COST             PIC S9(13)V99       COMP-3.
        01  WS-TAXRATE                PIC S9V99           COMP-3.
 
       LINKAGE SECTION.
 
        01  LS-PRICE                  PIC S9(8)V9(2)      COMP-3.
        01  LS-QUANTITY               PIC S9(4)           COMP-4.
        01  LS-TAXRATE                PIC SV99            COMP-3.
        01  LS-TOTAL-COST             PIC $$,$$$,$$$,$$$,$$$.99
                                                          DISPLAY.
        01  LS-OPERATION-SUCCESSFUL   PIC X               DISPLAY.
 
PROCEDURE DIVISION  USING  LS-PRICE                                            0
                           LS-QUANTITY
                           LS-TAXRATE
                           LS-TOTAL-COST
                           LS-OPERATION-SUCCESSFUL.
 
 MAINLINE.
    MOVE "Y" TO LS-OPERATION-SUCCESSFUL.
    PERFORM CALCULATE-COST.
    PERFORM FORMAT-COST.
    EXIT PROGRAM.
 
        CALCULATE-COST.
           MOVE LS-TAXRATE TO WS-TAXRATE.
           ADD 1 TO WS-TAXRATE.
           COMPUTE  WS-TOTAL-COST ROUNDED = LS-QUANTITY *
                                            LS-PRICE *
                                            WS-TAXRATE
             ON SIZE ERROR
               MOVE "N" TO LS-OPERATION-SUCCESSFUL
           END-COMPUTE.
 
        FORMAT-COST.
           MOVE WS-TOTAL-COST TO LS-TOTAL-COST.

OPM RPG Program T2123RP1

The OPM RPG program T2123RP1 contains the WriteAuditTrail() function which writes the audit trail for the program.

FT2123DD2O   E                    DISK                      A
F            T2123DD2R                         KRENAMEDD2R
IQTYIN       DS
I                                    B   1   40QTYBIN
C           *ENTRY    PLIST
C                     PARM           USER   10
C                     PARM           ITEM   20
C                     PARM           PRICE  102
C                     PARM           QTYIN
C                     PARM           TXRATE  22
C                     PARM           TOTAL  21
C                     EXSR ADDREC
C                     SETON                         LR
C           ADDREC    BEGSR
C                     MOVELUDATE     DATE
C                     MOVE QTYBIN    QTY
C                     WRITEDD2R
C                     ENDSR

Invoking the ILE-OPM Program

To enter data for the program T2123IC5 enter the command T2123CM2 and press F4 (Prompt).

You can enter this data into T2123CM2:

     Hammers
     1.98
     5000
     Nails
     0.25
     2000

The output is:

+--------------------------------------------------------------------------------+
|  5000 HAMMERS plus tax =            $11,385.00                                 |
|  Press ENTER to end terminal session.                                          |
|>                                                                               |
|  2000 NAILS plus tax =               $575.00                                   |
|  Press ENTER to end terminal session.                                          |
+--------------------------------------------------------------------------------+

The physical file T2123DD2 contains this data:

SMITHE  HAMMERS               0000000198500015          $11,385.0007     2893
SMITHE  NAILS                 0000000025200015             $575.0007     2893


[ Top of Page | Previous Page | Next Page | Table of Contents ]