One of my criticisms when using CL procedures in my RPG programs is that I had to use the name of the module. Sometimes the ten character name of the procedure, and module, was not descriptive enough for my sensibilities. I have discovered that a solution was provided in IBM i 7.2 that allows me to give my own name to CL procedures.
In this example what the code for the CL procedure is not necessary. All I need to know is that it will copy a file to a IFS folder. It has four parameters:
- Library the file is in
- File name
- Path name, directory and name the file will be called in the IFS
- A code returned from CL procedure to whatever called it
The CL procedure I will be using is in the module CLMODULE01. I can only have one CL procedure in a module, and the CLLE compiler gives the procedure the same name as the module. I think you will all agree that the name does not describe what it does. If this was a procedure I would give it another name when defining it in my RPG program.
I added the module to a binding directory, BINDINGDIR, in my library. I can check that it was added in one of two ways. The first is using the Working Binding Directory Entries command, WRKBNDDIRE, thus:
WRKBNDDIRE BINDINGDIR |
Which displays:
Work with Binding Directory Entries Binding Directory: BINDINGDIR Library: MYLIB Opt Object Type Library _ __________ _______ __________ _ CLMODULE01 *MODULE *LIBL |
I can also use the SQL View BINDING_DIRECTORY_INFO to do the same:
01 SELECT ENTRY_LIBRARY,ENTRY,ENTRY_TYPE 02 FROM QSYS2.BINDING_DIRECTORY_INFO 03 WHERE BINDING_DIRECTORY_LIBRARY = 'MYLIB' 04 AND BINDING_DIRECTORY = 'RPGPGM01' |
I am only interested in three columns returned by the View:
- ENTRY_LIBRARY: Which library to find the module in
- ENTRY: Name of module
- ENTRY_TYPE: The type of the entry, in this case it is a module rather than a service program
ENTRY_ ENTRY_ LIBRARY ENTRY TYPE ------- ---------- ------- *LIBL CLMODULE01 *MODULE |
As I have my module and binding directory ready I can create my RPG program:
01 **free 02 ctl-opt option(*srcstmt) dftactgrp(*no) bnddir('*LIBL/BINDINGDIR') ; 03 dcl-pr CpyFileToIFS extproc(*CL:'CLMODULE01') ; 04 *n char(10) const ; // Library 05 *n char(10) const ; // File 06 *n char(100) const ; // IFS path 07 *n char(1) ; // Return code 08 end-pr ; 09 dcl-s RtnCde char(1) ; 10 CpyFileToIFS('MYLIB' : 'TESTFILE' : '/home/mydir/testfile.txt' : RtnCde) ; |
Line 1: You should be using totally free format RPG.
Line 2: These are the control option I need for this program. I need the DFTACTGRP as I am calling an external procedure. I always like adding the BNDDIR so that no-one can forget to use this binding directory when compiling this program.
Lines 3 – 8: The prototype definition for my CL procedure.
Line 3: Here is where I give the procedure the name I want, CpyFileToIFS, rather than use the CL module's name. I have the EXTPROC with *CL to denote that the procedure is written in CL, followed by the procedure's name.
Lines 4 – 7: I never bother to give my procedure parameters names. The ones that are followed by CONST will be passed as strings.
Line 9: This variable definition is for the variable I will be receiving the returned code into.
Line 10: I am calling my CL procedure with the name I gave it.
I can now create my RPG program. As my binding directory is given in the control options the CLMODULE01 is bound into the final program. How can I know that? It should come as no surprise there are two ways.
The first way I could check is using the Display Program command, DSPPGM:
DSPPGM PGM(RPGPGM01) DETAIL(*MODULE) |
Which gives me:
Display Program Information Program . . . . . . : RPGPGM01 Library . . . . . . : MYLIB Owner . . . . . . . : SIMON Program attribute . : RPGLE Detail . . . . . . . : *MODULE Opt Module Library Attribute _ RPGPM01 QTEMP RPGLE _ CLMODULE01 MYLIB CLLE |
Or I can use the SQL View BOUND_MODULE_INFO:
01 SELECT BOUND_MODULE_LIBRARY AS "Mod lib", 02 BOUND_MODULE AS "Module", 03 MODULE_ATTRIBUTE AS "Type" 04 FROM QSYS2.BOUND_MODULE_INFO 05 WHERE PROGRAM_LIBRARY = 'MYLIB' 06 AND PROGRAM_NAME = 'RPGPGM01' 07 AND OBJECT_TYPE = '*PGM' |
Lines 1 – 3: I am only interested in the columns:
- BOUND_MODULE_LIBRARY: Library the bound modules are in
- BOUND_MODULE: Names of the modules
- MODULE_ATTRIBUTE: Their attribute
The results are:
Mod lib Module Type ------- ---------- ----- QTEMP RPGPGM01 RPGLE MYLIB CLMODULE01 CLLE |
I am so pleased to have found the ability for me to give the CL procedures more descriptive names I am tempted to modify some of my existing programs to add this to them.
You can learn more about the enhancements to the RPG's procedure prototype's external procedure parameter from the IBM website here.
This article was written for IBM i 7.5, and should work for some earlier releases too.
No comments:
Post a Comment
To prevent "comment spam" all comments are moderated.
Learn about this website's comments policy here.
Some people have reported that they cannot post a comment using certain computers and browsers. If this is you feel free to use the Contact Form to send me the comment and I will post it for you, please include the title of the post so I know which one to post the comment to.