To improve the flexibility of your RPG coding, and to help protect the integrity of the calling program's data, learn to use read-only reference where appropriate.
Editor's note: This TechTip is an excerpt from the book Programming in RPG IV, 4th Edition.
Prototypes provide an effective way to describe the data items to be passed between programs. Prototypes also offer some flexibility in the method the system will use to pass those parameters.
By default, RPG IV passes parameter arguments by sharing the address of the storage location represented by the variable (passing by reference). If the called program changes the value of the parameter variable, the change will be recognized by the calling program. When a program passes a parameter by reference, the parameter's value must exist within a variable; to pass the parameter, you name the variable in parentheses following the Callp operation.
While passing by reference is the default, prototypes support an alternative method of passing parameters between programs: read-only reference. Passing parameters by read-only reference offers several advantages over passing parameters by reference:
- The parameter values need not be represented in a variable.
- The parameter data types need not exactly match the prototype.
- The system offers some protection against the parameter values being changed by the called program.
On occasion, you may want to be able to pass expressions or literals, instead of variables, to dynamically called programs. This capability gives you more flexibility in coding the Callp operation than being limited to representing the parameter value in a variable. When RPG IV passes a parameter by read-only reference, it can first evaluate an expression or a literal and then make a temporary copy of that value before invoking the called program; the calling program will then pass a pointer to the memory occupied by the copy. To specify read-only reference, you code the Const keyword in the prototype:
*.. 1 ...+... 2 ...+... 3 ...+... 4 ...+... 5 ...+... 6 ...+... 7 ...+... 8
DName+++++++++++ETDsFrom+++To/L+++IDc.Functions++++++++++++++++++++++++++++
D Updcust PR Extpgm('AR003')
D 5 0 Const
D 7 0 Const
/Free
Updcust(5:Custnumber);
/End-Free
This example calls a program, passing two parameters; the first parameter is passed as a literal (5), while the second one is passed as a variable (Custnumber). You could also code an expression as the parameter when passing by read-only reference:
*.. 1 ...+... 2 ...+... 3 ...+... 4 ...+... 5 ...+... 6 ...+... 7 ...+... 8
DName+++++++++++ETDsFrom+++To/L+++IDc.Functions++++++++++++++++++++++++++++
D Addcust PR Extpgm('AR001')
D 5 0 Const
D 7 0 Const
/Free
Updcust(5 : Lastcustomer + 1);
/End-Free
In the preceding example, the second parameter is an expression. You can mix passing methods in the same prototype, if necessary. If you omit the Const keyword for a parameter, the parameter is passed by reference.
The Const keyword allows you some flexibility in passing parameters of slightly different data formats than the prototype specifies. For example, you might pass an integer when a prototype calls for a packed decimal field. As long as the field's value is appropriate for the data type, the prototype will manage this minor mismatch.
When a program passes a parameter by read-only reference, the called program should avoid changing the value of that parameter. Because the passed parameter may be a copy of the actual information, the calling program may not see any changes that the called program makes to that parameter value. Indeed, if the called program includes a prototype and a procedure interface, the compiler will prevent the program from changing the parameter. In the following example, program AR001, the called program, would not be allowed to change the values of Company or Customer:
Calling program:
*.. 1 ...+... 2 ...+... 3 ...+... 4 ...+... 5 ...+... 6 ...+... 7 ...+... 8
DName+++++++++++ETDsFrom+++To/L+++IDc.Functions++++++++++++++++++++++++++++
D Addcust PR Extpgm('AR001')
D 5 0 Const
D 7 0 Const
/Free
Updcust(5 : Lastcustomer + 1);
/End-Free
Called program:
*.. 1 ...+... 2 ...+... 3 ...+... 4 ...+... 5 ...+... 6 ...+... 7 ...+... 8
DName+++++++++++ETDsFrom+++To/L+++IDc.Functions++++++++++++++++++++++++++++
D Main PR Extpgm('AR001')
D 5 0 Const
D 7 0 Const
D Main PI
D Company 5 0 Const
D Customer 7 0 Const
/Free
// (Some processing goes here...cannot change Company or Customer)
*Inlr = *On;
Return;
/End-Free
If the called program does not have a PR/PI combination—for example, if the called program is written in another language that does not support prototyping, such as CL—it may be allowed to change the parameter values, but you should avoid doing so, since you cannot be sure whether or not the calling program will recognize the change.
Tip: To improve the flexibility of your coding, and to help protect the integrity of the calling program's data, use read-only reference as the preferred method for passing parameters between programs. If the calling program needs to access any changes made by the called program, pass by reference; or if there is a large number of parameters to be passed, pass by reference to improve the performance of the call.
LATEST COMMENTS
MC Press Online