ILE C/C++ Programmer's Guide

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

This application uses session input to:

Note:
For the ILE version of this example, see ILE CL Example: Calling OPM, COBOL, and RPG Programs from an ILE C Program.

As shown in Basic Program StructureFigure 253, the application is a small transaction processing program that takes name, price, and quantity as input items. As output, the application displays the total cost of the items that are specified on the screen and writes an audit trail of transactions to a file.

Basic Program Structure

Figure 253. OPM CL Example: Basic Program Structure


As shown in Basic Program StructureFigure 253, this example consists of:

Note:
In addition to the source for CMD, CL, ILE C, OPM RPG, and OPM COBOL, you need DDS source for the output file. The DDS source defines the fields for the audit file.

Program Modules and Activation Groups

As shown in Figure 254, the CL, COBOL, and RPG programs are activated within the user default activation groups. A new activation group is started when the CL programs call the ILE C program because the ILE C program is created with the CRTPGM default of *NEW for the ACTGRP keyword.

Note:
When a CRTPGM parameter does not appear in the CRTBNDC command, the CRTPGM parameter default is used.

Figure 254. Structure of the Program in ILE C


These programming steps show you how to:

Programming Tasks

  1. Create the physical file T1520DD2 using the source shown in Figure 255. On a command line, enter:

    CRTPF FILE(MYLIB/T1520DD2) SRCFILE(QCPPLE/QADDSSRC) MAXMBRS(*NOMAX)

    This source file contains the audit trail for the ILE C program T1520IC5.

    Figure 255. T1520DD2 -- DDS Source for an Audit File


    
    
    R T1520DD2R
    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
    Note:
    The DDS source defines the fields for the audit file.
  2. Create the CL program T1520CL2 using the source shown in Figure 256. On a command line, enter:

    CRTCLPGM PGM(MYLIB/T1520CL2) SRCFILE(QCPPLE/QACLSRC)

    Figure 256. T1520CL2 -- CL Source to Pass Variables to an ILE C Program


    
    
    PGM PARM(&ITEMIN &PRICE &QUANTITY)
    DCL VAR(&USER) TYPE(*CHAR) LEN(10)
    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)
    /* GET THE USERID FOR THE AUDIT FILE */
    RTVJOBA USER(&USER)
    /* ENSURE AUDIT RECORDS WRITTEN TO CORRECT AUDIT FILE MEMBER */
    OVRDBF FILE(T1520DD2) TOFILE(*LIBL/T1520DD2) +
    MBR(T1520DD2) OVRSCOPE(*CALLLVL) SHARE(*NO)
    CALL PGM(T1520IC5) PARM(&ITEMOUT &PRICE &QUANTITY +
    &USER)
    DLTOVR FILE(*ALL)
    ENDPGM

    Notes:

    1. CL variables item name, price, quantity, and user ID are passed by reference to the ILE C program T1520IC5.

    2. The Retrieve Job Attributes (RTVJOBA) command obtains the user ID for the audit trail.

    3. Arguments are passed by reference. They can be changed by the receiving ILE C program.

    4. The variable item_name is null-ended in the CL program.

    5. CL variables and numeric constants are not passed to an ILE C program with null-ended strings.

    6. Character constants and logical literals are passed as null-ended strings, but are not widened with blanks.

    7. Numeric constants such as packed decimals are passed as 15,5 (8 bytes).

    8. Floating point constants are passed as double precision floating point values, for example 1.2E+15.

    9. To pass parameters to an ILE program when you run it, use the PARM option of the CL Call (CALL) command.
  3. Create a CL command prompt T1520CM2 to enter the item name, price, and quantity for the ILE C program T1520IC5. Use the source shown in Figure 257. On a command line, enter:

    CRTCMD CMD(MYLIB/T1520CM2) PGM(MYLIB/T1520CL2) SRCFILE(QCPPLE/QACMDSRC)

    Figure 257. T1520CM2 -- CL Command Source to Receive Input Data


    
    
    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)
  4. Create the program T1520IC5 using the source shown in Figure 258. On a command line, enter:

    CRTBNDC PGM(MYLIB/T1520IC5) SRCFILE(QCPPLE/QACSRC) OUTPUT(*PRINT) FLAG(30)
    OPTION(*SHOWINC *NOLOGMSG) MSGLMT(10) CHECKOUT(*PARM) DBGVIEW(*ALL)

    Figure 258. T1520IC5 -- ILE C Source to Call COBOL AND RPG



    
    
    /* This program is called by a CL program that passes an item */
    /* name, price, quantity and user ID. */
    /* COBOL for iSeries 400 is called to calculate and format the total cost. */
    /* RPG for iSeries 400 is called to write an audit trail. */
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <decimal.h>
    /* The #pragma map directive maps a new program name to the existing */
    /* program name so that the purpose of the program is clear. */
    #pragma map(calc_and_format,"T1520CB1")
    #pragma map(write_audit_trail,"T1520RP1")
    /* Tell the compiler that there are dynamic program calls so */
    /* arguments are passed by value-reference. */
    #pragma linkage(calc_and_format, OS, nowiden)
    #pragma linkage(write_audit_trail, OS)
    void calc_and_format(decimal (10,2),
    short int,
    decimal(2,2),
    char[],
    char *);
    void write_audit_trail(char[],
    char[],
    decimal(10,2),
    short int,
    decimal(2,2),
    char[]);
    int main(int argc, char *argv[])
    {
    /* Incoming arguments from a CL program have been verified by */
    /* the *CMD and null ende within the CL program. */
    /* Incoming arguments are passed by reference from a CL program. */
    char *user_id;
    char *item_name;
    short int quantity;
    decimal (10, 2) price;
    decimal (2,2) taxrate = .15D;
    char formatted_cost[22];

    
    
    /* Remove null end for RPG for iSeries 400 program. Item name is null */
    /* ended 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 = *((decimal (10, 2) *) argv[2]);
    quantity = *((short *) argv[3]);
    user_id = argv[4];

    /* Call the COBOL for iSeries 400 program to do the calculation, and return a */
    /* Y/N flag, and a formatted result. */

    calc_and_format(price,
    quantity,
    taxrate,
    formatted_cost,
    &success_flag);
    memcpy(null_formatted_cost,formatted_cost,sizeof(formatted_cost));

    /* Null end the result. */
    formatted_cost[21] = '\0';
    if (success_flag == 'Y')
    {
    for (i=0; i<20; i++)
    {

    /* Remove null end for the RPG for iSeries 400 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. */
    write_audit_trail(user_id,
    rpg_item_name,
    price,
    quantity,
    taxrate,
    formatted_cost);

    printf("\n%d %s plus tax = %-s\n", quantity,
    item_name,
    null_formatted_cost);
    }
    else
    {
    printf("Calculation failed\n");
    }
    }

    Notes:

    1. The main() function in this program receives incoming arguments from CL program T1520CL2 that are verified by CL command prompt T1520CM2 and null ended within CL program T1520CL2. All incoming arguments are pointers.

    2. The main() function also calls calc_and_format(), which is mapped to a COBOL name. It passes by OS-linkage convention the price, quantity, taxrate, formatted cost, and a success flag.

    3. Because the OPM COBOL program is not expecting widened parameters (the default for ILE C), nowiden is used in the #pragma linkage directive. The formatted cost and the success flag values are updated in program T1520IC5.

    4. If calc_and_format() returns successfully a record is written to the audit trail by write_audit_trail() in the OPM RPG program. The main() function in this program (T1520IC5) calls write_audit_trail() which is mapped to an RPG for iSeries 400 program name. It passes by OS-linkage convention the user ID, item name, price, quantity, taxrate, and formatted cost.

    5. The ILE Compiler by default converts a short integer to an integer unless the nowiden parameter is specified on the #pragma linkage directive. For example, the short integer in the ILE 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.

    6. OUTPUT(*PRINT) specifies that you want a compiler listing. OPTION(*SHOWINC *NOLOGMSG) specifies that you want to expand include files in a compiler listing, and not log CHECKOUT option messages.

    7. FLAG(30) specifies that you want severity level 30 messages to appear in the listing. MSGLMT(10) specifies that you want compilation to stop after 10 messages at severity level 30. CHECKOUT(*PARM) shows a list of function parameters that are not used. DBGVIEW(*ALL) specifies that you want all three views and debug data to debug this program.
  5. Create an OPM COBOL program using the source shown in Figure 259. On a command line, enter:

    CRTCBLPGM PGM(MYLIB/T1520CB1) SRCFILE(QCPPLE/QALBLSRC)

    Figure 259. T1520CB1 -- OPM COBOL Source to Calculate Tax and Format Cost


    
    
    IDENTIFICATION DIVISION.
    PROGRAM-ID. T1520CB1.
    ******************************************************
    * 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.

    Notes:

    1. This program receives pointers to the values of the variables price, quantity, and taxrate, and pointers to formatted_cost and success_flag.

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

    3. The COBOL/400 User's Guide (http://publib.boulder.ibm.com/iseries/v5r1/ic2924/books/c0918120.pdf) contains information on how to compile an OPM COBOL program.
  6. Create an OPM RPG program using the source shown in Figure 260. On a command line, enter:

    CRTRPGPGM PGM(MYLIB/T1520RP1) SRCFILE(QCPPLE/QARPGSRC) OPTION(*SOURCE *SECLVL)

    Figure 260. T1520RP1 -- OPM RPG Source to Write the Audit Trail


    
    
    FT1520DD2O E DISK A
    F T1520DD2R 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

    Notes:

    1. The write_audit_trail() function in the program T1520RP1 writes the audit trail for the program.

    2. The RPG/400 User's Guide contains information on how to compile an OPM RPG program.
  7. Enter data for the program T1520IC5.
    1. On a command line, type:

      T1520CM2
      and press F4 (Prompt).
    2. Type the following data into T1520CM2:
      
      
      Hammers
      1.98
      5000
      Nails
      0.25
      2000

    The output is as follows:

    +--------------------------------------------------------------------------------+
    |  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 T1520DD2 contains the data as follows:


    SMITHE HAMMERS 0000000198500015 $11,385.00072893
    SMITHE NAILS 0000000025200015 $575.00072893


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