ILE C/C++ Programmer's Guide

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

This example is an ILE version of the small transaction processing program OPM CL Example: Calling OPM, COBOL, and RPG Programs from an ILE C Program.

Figure 261. Basic Object Structure


This example consists of:

Note:
In addition to the source for CMD, ILE CL, ILE C, ILE RPG and ILE COBOL you need DDS source for the output file, which is the same as the previous example.

Program Modules and Activation Groups

As shown in Figure 262, the CL and C programs are activated within a new activation group. The ILE CL program is created with the CRTPGM default for the ACTGRP parameter, ACTGRP(*NEW). The ILE C program is created with ACTGRP(*CALLER).

Figure 262. Integrated Language Environment Structure


Programming Tasks

The following steps show you how to:

  1. To create a physical file T1520DD2 using the source shown in Figure 263, enter:

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

    Figure 263. T1520DD2 -- Source to Create Physical Files


    
    
    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

    This file contains the audit trail for the ILE C program T1520ICB.

  2. To create a CL program T1520CL3 that the source shown in Figure 264, enter:

    CRTCLMOD MODULE(MYLIB/T1520CL3) SRCFILE(QCPPLE/QACLSRC)
    CRTPGM PGM(MYLIB/T1520CL3) MODULE(MYLIB/T1520CL3) ACTGRP(*NEW)

    Figure 264. T1520CL3 -- ILE CL Source to Pass Variables to an ILE C Program


    
    
    /* ILE version of T1520CL2 */
    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(T1520ICB) PARM(&ITEMOUT &PRICE &QUANTITY +
    &USER)
    DLTOVR FILE(*ALL)
    ENDPGM
    Note:
    To pass parameters to an ILE program when you run it, use the PARM option of
    the CL Call (CALL) command.

    This program passes the CL variables item name, price, quantity, and user ID by reference to an ILE C program T1520ICB. 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 variable item_name is null ended in the CL program.

  3. To create a CL command prompt T1520CM2 using the source in Figure 265, enter:

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

    Figure 265. T1520CM2 -- Source to Create a CL Command Prompt


    
    
    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)

    You use this CL command to enter the item name, price, and quantity for the ILE C program T1520ICB.

  4. To create the module T1520ICB using the source shown in Figure 266, enter:

    CRTCMOD MODULE(MYLIB/T1520ICB) SRCFILE(QCPPLE/QACSRC)

    Figure 266. T1520ICB -- ILE C Source to Call COBOL and RPG Procedures


    
    
    /* This program demonstrates the interlanguage call capability */
    /* of an ILE C program. This program is called by a CL */
    /* program that passes an item name, price, quantity and user ID. */
    /* A COBOL procedure is called to calculate and format total cost.*/
    /* An RPG procedure 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 function name to the bound */
    /* procedure name so that the purpose of the procedure is clear. */
    #pragma map(calc_and_format,"T1520CB2")
    #pragma map(write_audit_trail,"T1520RP2")
    /* Tell the compiler that there are bound procedure calls and */
    /* arguments are to be passed by value-reference. */
    #pragma argument(calc_and_format, OS, nowiden)
    #pragma argument(write_audit_trail, OS)
    void calc_and_format(decimal (10,2),
    short int,
    char[],
    char *);
    void write_audit_trail(char[],
    char[],
    decimal(10,2),
    short int,
    char[]);
    extern decimal (2,2) TAXRATE; /* TAXRATE is in *SRVPGM T1520SP3 */
    int main(int argc, char *argv[])
    {
    /* Incoming arguments from a CL program have been verified by */
    /* the *CMD and null ended 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;
    char formatted_cost[22];
    /* Remove null terminator 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 program to do the calculation, and return a */
    /* Y/N flag, and a formatted result. */
    calc_and_format(price,
    quantity,
    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 the 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,
    formatted_cost);

    printf("\n%d %s plus tax = %-s\n", quantity,
    item_name,

    }
    else
    {
    printf("Calculation failed\n");
    }
    }

    Notes:

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

    2. The main() function in this program calls calc_and_format() which is mapped to a ILE COBOL procedure name. It passes by OS-linkage convention the price, quantity, formatted cost, and a success flag. The ILE OPM COBOL procedure is not expecting widened parameters, the default for ILE C. This is why nowiden is used in the #pragma argument directive. The formatted cost and the success flag values are updated in the procedure T1520CB2.

    3. If calc_and_format() return successfully the main() function in this program (T1520ICB) calls write_audit_trail() which is mapped to an ILE RPG procedure name. It passes by OS-linkage convention (also called by value-reference) the user ID, item name, price, quantity, and formatted cost. The ILE C compiler by default converts a short integer to an integer unless the nowiden parameter is specified on the #pragma argument directive. For example, the short integer in the ILE C program is converted to an integer, and then passed to the ILE RPG procedure. The RPG procedure is expecting a 4 byte integer for the quantity variable.
  5. To create module T1520ICC using the source shown in Figure 267, enter:

    CRTCMOD MODULE(MYLIB/T1520ICC) SRCFILE(QCPPLE/QACSRC)

    Figure 267. T1520ICC -- Source Code to Export Tax Rate Data



    /* Export the tax rate data. */
    #include <decimal.h>
    const decimal (2,2) TAXRATE = .15D;

    TAXRATE is exported from this module to ILE C, COBOL, and RPG procedures.

    Note:
    Weak definitions (EXTERNALs from COBOL) cannot be exported out of a service program to a strong definition language like C. C can export to COBOL, hence the choice of language for TAXRATE.
  6. To create an ILE COBOL procedure using the source shown in Figure 268, enter:

    CRTCBLMOD MODULE(MYLIB/T1520CB2) SRCFILE(QCPPLE/QALBLSRC)

    Figure 268. T1520CB2 -- ILE COBOL Source to Calculate Tax and Format Cost


    
    
    IDENTIFICATION DIVISION.
    PROGRAM-ID. T1520CB2 INITIAL.
    ******************************************************
    * parameters: *
    * incoming: PRICE, QUANTITY *
    * returns : TOTAL-COST (PRICE*QUANTITY*1.TAXRATE) *
    * SUCCESS-FLAG. *
    * TAXRATE : An imported value. *
    ******************************************************
    ENVIRONMENT DIVISION.
    CONFIGURATION SECTION.
    SOURCE-COMPUTER. IBM-ISERIES.
    OBJECT-COMPUTER. IBM-ISERIES.
    DATA DIVISION.
    WORKING-STORAGE SECTION.
    01 WS-TOTAL-COST PIC S9(13)V99 COMP-3.
    01 WS-TAXRATE PIC S9V99 COMP-3
    VALUE 1.
    01 TAXRATE EXTERNAL PIC SV99 COMP-3.
    LINKAGE SECTION.
    01 LS-PRICE PIC S9(8)V9(2) COMP-3.
    01 LS-QUANTITY PIC S9(4) COMP-4.
    01 LS-TOTAL-COST PIC $$,$$$,$$$,$$$,$$$.99
    DISPLAY.
    01 LS-OPERATION-SUCCESSFUL PIC X DISPLAY.
    
    
    PROCEDURE DIVISION USING LS-PRICE
    LS-QUANTITY
    LS-TOTAL-COST
    LS-OPERATION-SUCCESSFUL.
    MAINLINE.
    MOVE "Y" TO LS-OPERATION-SUCCESSFUL.
    PERFORM CALCULATE-COST.
    PERFORM FORMAT-COST.
    EXIT PROGRAM.
    CALCULATE-COST.
    ADD TAXRATE 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 and quantity, and pointers to formatted_cost and success_flag.

    2. The calc_and_format() function is procedure T1520CB2. It calculates and formats the total cost.

    3. The WebSphere Development Studio: ILE COBOL Programmer's Guide contains information on how compile an ILE COBOL source program.
  7. To create an ILE RPG procedure using the source shown in Figure 269, enter:

    CRTRPGMOD MODULE(MYLIB/T1520RP2) SRCFILE(QCPPLE/QARPGSRC)

    Figure 269. T1520RP2 -- ILE RPG Source to Write the Audit Trail


    
    
    FT1520DD2 O A E DISK
    D TAXRATE S 3P 2 IMPORT
    D QTYIN DS
    D QTYBIN 1 4B 0
    C *ENTRY PLIST
    C PARM USER 10
    C PARM ITEM 20
    C PARM PRICE 10 2
    C PARM QTYIN
    C PARM TOTAL 21
    C EXSR ADDREC
    C SETON LR
    C ADDREC BEGSR
    C MOVEL UDATE DATE
    C MOVE QTYBIN QTY
    C MOVE TAXRATE TXRATE
    C WRITE T1520DD2R
    C ENDSR

    Notes:

    1. The write_audit_trail() function is the procedure T1520RP2. It writes the audit trail for the program.

    2. The WebSphere Development Studio: ILE RPG Programmer's Guide contains information on how to compile an ILE RPG source program.
  8. To create the service program T1520SP3 from the module T1520ICC, enter:

    CRTSRVPGM SRVPGM(MYLIB/T1520SP3) MODULE(MYLIB/T1520ICC) +
    EXPORT(*SRCFILE) SRCFILE(QCPPLE/QASRVSRC)
    The T1520SP3 service program exports taxrate. The export list is specified in T1520SP3 in QASRVSRC.
  9. To create the service program T1520SP4 from the module T1520RP2, enter:

    CRTSRVPGM SRVPGM(MYLIB/T1520SP4) MODULE(MYLIB/T1520RP2) +
    EXPORT(*SRCFILE) SRCFILE(QCPPLE/QASRVSRC)
    The T1520SP4 service program exports procedure T1520RP2. The export list is specified in T1520SP4 in QASRVSRC.
  10. To create the program T1520ICB enter:

    CRTPGM PGM(MYLIB/T1520ICB) MODULE(MYLIB/T1520ICB MYLIB/T1520CB2) +
    BNDSRVPGM(MYLIB/T1520SP3 MYLIB/T1520SP4) ACTGRP(*CALLER)
    T1520ICB is considered the application's main program. It will run in the new activation group that was created when T1520CL3 was called.
  11. To enter data for the program T1520ICB, type T1520CM2and press F4 (Prompt).:

    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 following data:


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


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