CALL/CALLB/CALLP的区别
https://www.ibm.com/docs/en/i/7.2?topic=operations-call#yycall
使用场景
CALL/CALLB/CALLP 均可用于传统格式rpg,但在free-style下只能使用CALLP
效率
CALLB : 比CALL快5倍
CALLP : 比CALL快100倍
(数据来源于论坛:https://www.mcpressonline.com/forum/forum/programming/rpg/12881-callp-vs-callb)
官方建议无论在哪个场景下使用CALLP :
The recommended way to call a program or procedure (written in any language) is to code a prototyped call.
示例
CALL
*...1....+....2....+....3....+....4....+....5....+....6....+....7....+....
CL0N01Factor1+++++++Opcode(E)+Factor2+++++++Result++++++++Len++D+HiLoEq....
* The CALL operation calls PROGA and allows PROGA to access
* FieldA and FieldB, defined elsewhere. PROGA is run using the content
* of FieldA and FieldB. When PROGA has completed, control
* returns to the statement following the last PARM statement.
*
*
C CALL 'PROGA'
C PARM FieldA
C PARM FieldB
CALLB
DName+++++++++++ETDsFrom+++To/L+++IDc.Keywords+++++++++++++++++++++++++++++
* Define a procedure pointer
D
D ProcPtr S * PROCPTR INZ(%PADDR('Create_Space'))
D Extern S 10
D
CL0N01Factor1+++++++Opcode(E)+Factor2+++++++Result++++++++Len++D+HiLoEq....
* The following call linkage would be STATIC
C CALLB 'BOUNDPROC'
* The following call linkage would be DYNAMIC
C CALL Extern
* The following call linkage would be STATIC, using a procedure pointer
C CALLB ProcPtr
CALLP
- Calling a Prototyped Program Using CALLP
*..1....+....2....+....3....+....4....+....5....+....6....+....7...+....
*-------------------------------------------------------------
* This prototype for QCMDEXC defines two parameters:
* 1- a character field that may be shorter in length
* than expected
* 2- any numeric field
*-------------------------------------------------------------
D qcmdexc PR extpgm('QCMDEXC')
D cmd 200A options(*varsize) const
D cmdlen 15P 5 const
/FREE
qcmdexc ('WRKSPLF' : %size ('WRKSPLF'));
/END-FREE
- Passing an array parameter using CALLP
* The prototype for the procedure has an array parameter.
D proc pr
D parm 10a dim(5)
* An array to pass to the procedure
D array s 10a dim(5)
* Call the procedure, passing the array
C callp proc (array)
- Calling a Prototyped Procedure Using CALLP
*..1....+....2....+....3....+....4....+....5....+....6....+....7...+....
*=================================================================*
* CvtToHex - convert input string to hex output string *
*=================================================================*
D/COPY MYLIB/QRPGLESRC,CVTHEXPR
*-----------------------------------------------------------------*
* Main entry parameters *
* 1. Input: string character(n) *
* 2. Output: hex string character(2 * n) *
*-----------------------------------------------------------------*
D CvtToHex PI OPDESC
D InString 16383 CONST OPTIONS(*VARSIZE)
D HexString 32766 OPTIONS(*VARSIZE)
*-----------------------------------------------------------------*
* Prototype for CEEDOD (Retrieve operational descriptor) *
*-----------------------------------------------------------------*
D CEEDOD PR
D 10I 0 CONST
D 10I 0
D 10I 0
D 10I 0
D 10I 0
D 10I 0
D 12A OPTIONS(*OMIT)
* Parameters passed to CEEDOD
D ParmNum S 10I 0
D DescType S 10I 0
D DataType S 10I 0
D DescInfo1 S 10I 0
D DescInfo2 S 10I 0
D InLen S 10I 0
D HexLen S 10I 0
*-----------------------------------------------------------------*
* Other fields used by the program *
*-----------------------------------------------------------------*
D HexDigits C CONST('0123456789ABCDEF')
D IntDs DS
D IntNum 5I 0 INZ(0)
D IntChar 1 OVERLAY(IntNum:2)
D HexDs DS
D HexC1 1
D HexC2 1
D InChar S 1
D Pos S 5P 0
D HexPos S 5P 0
/FREE
//-------------------------------------------------------------//
// Use the operational descriptors to determine the lengths of //
// the parameters that were passed. //
//-------------------------------------------------------------//
CEEDOD (1 : DescType : DataType :
DescInfo1 : DescInfo2 : Inlen : *OMIT);
CEEDOD (2 : DescType : DataType :
DescInfo1 : DescInfo2 : HexLen : *OMIT);
//-------------------------------------------------------------//
// Determine the length to handle (minimum of the input length //
// and half of the hex length) //
//-------------------------------------------------------------//
if InLen > HexLen / 2;
InLen = HexLen / 2;
endif;
//-------------------------------------------------------------//
// For each character in the input string, convert to a 2-byte //
// hexadecimal representation (for example, '5' --> 'F5') //
//-------------------------------------------------------------//
HexPos = 1;
for Pos = 1 to InLen;
InChar = %SUBST(InString : Pos :1);
exsr GetHex;
%subst (HexString: HexPos: 2) = HexDs;
HexPos = HexPos + 2;
endfor;
return;
//================================================================//
// GetHex - subroutine to convert 'InChar' to 'HexDs' //
// Use division by 16 to separate the two hexadecimal digits. //
// The quotient is the first digit, the remainder is the second. //
//================================================================//
begsr GetHex;
IntChar = InChar;
//-----------------------------------------------------//
// Use the hexadecimal digit (plus 1) to substring the //
// list of hexadecimal characters '012...CDEF'. //
//-----------------------------------------------------//
HexC1 = %subst (HexDigits: %div(IntNum:16) + 1: 1);
HexC2 = %subst (HexDigits: %rem(IntNum:16) + 1: 1);
endsr; // GetHex