RTNPARM

The RTNPARM keyword specifies that the return value of a procedure is to be handled internally as a parameter of the same type as the defined returned value, passed by reference.

Using RTNPARM may improve performance when returning large values.

The impact on performance due to the RTNPARM keyword will vary from having a small negative impact to having a large positive impact. There may be a small negative impact when the prototyped return value is relatively small, such as an integer, or a small data structure. There will be some improvement when the prototyped return value is a larger value such as a 32767 byte data structure. The performance improvement is most apparent when the prototyped return value is a large varying length string, and the actual returned value is relatively small; for example, the prototype defines the return value as a one million byte varying length character string, and the value 'abc' is returned.

Using RTNPARM for a procedure prototype may also reduce the amount of automatic storage required for other procedures that contain calls to that procedure. For example, if procedure MYCALLER contains a call to procedure MYPROC that returns a large value, procedure MYCALLER will require additional automatic storage (even if MYCALLER does not actually call procedure MYPROC at run time). In some cases, procedure MYCALLER will not compile due to excessive automatic storage requirements; in other cases, MYCALLER is not able to be called because the total automatic storage on the call stack would exceed the maximum. Using RTNPARM avoids this problem with additional automatic storage.

Note:
  1. The additional parameter is passed as the first parameter.
  2. The %PARMS and %PARMNUM built-in functions include the additional parameter in the parameter count. When the RTNPARM keyword is specified, the value returned by %PARMNUM will be one higher than the apparent parameter number.
  3. When calling APIs that require a parameter number, such as CEEDOD or CEETSTA, you must account for the extra first parameter. For example, if your procedure has three parameters, and you want to find the length of the third parameter as it appears in your parameter list, you must ask for information about the fourth parameter. If you use the %PARMNUM built-in function to return the correct parameter number for calling these APIs, you do not need to worry about manually determining the correct parameter number.
  4. When the calling procedure is written in a language other than RPG, the caller must code the call as though the procedure has no return value, and as though there is an additional first parameter passed by reference with the same type as the RPG return value.
  5. Similarly, when the called procedure is written in a language other than RPG, the procedure must be coded without a return value, and having an additional first parameter passed by reference with the same type as the RPG return value.
  6. When RTNPARM is specified for the procedure, the maximum number of prototyped parameters is 398.
  7. The RTNPARM keyword is not allowed for a Java™ method call.

The RTNPARM keyword applies both to a prototype definition and to a procedure-interface definition.

Figure 1. Example of a procedure with the RTNPARM keyword
1. The prototype for the procedure
D center          pr        100000a   varying
D                                     rtnparm
D   text                     50000a   const varying
D   len                         10i 0 value


2. Calling the procedure
D title           s            100a   varying
 /free
    title = center ('Chapter 1' : 20);
    // title = '     Chapter 1     '

3.The procedure
P center          b                   export
D center          pi        100000a   varying
D                                     rtnparm
D   text                     50000a   const varying
D   len                         10i 0 value
D blanks          s          50000a   inz(*blanks)
D numBlanks       s             10i 0
D startBlanks     s             10i 0
D endBlanks       s             10i 0
 /free
    if len < %len(text);
       ... handle invalid input
    endif;
    numBlanks = len - %len(text);
    startBlanks = numBlanks / 2;
    endBlanks = numBlanks - startBlanks;
    return %subst(blanks : 1 : startBlanks)
         + text
         + %subst(blanks : 1 : endBlanks);
 /end-free
P center          e
Figure 2. Using %PARMS and calling CEEDOD with the RTNPARM keyword

D proc            pi              a   len(16773100) varying
D                                     rtnparm opdesc
D   p1                          10a
D   p2                          10a   options(*varsize)
D   p3                          10a   options(*omit : *nopass)

D num_parms       s             10i 0
D parm_len        s             10i 0
D desc_type       s             10i 0
D data_type       s             10i 0
D desc_info1      s             10i 0
D desc_info2      s             10i 0
D CEEDOD          pr
D   parm_num                    10i 0 const
D   desc_type                   10i 0
D   data_type                   10i 0
D   desc_info1                  10i 0
D   desc_info2                  10i 0
D   parm_len                    10i 0
D   feedback                    12a   options(*omit)
 /free
    // Get information about parameter p2
    callp CEEDOD(%parmnum(p2) : desc_type : data_type
               : desc_info1 : desc_info2
               : parm_len : *omit);
    if parm_len < 10;
       // The parameter passed for p2 is shorter than 10
    endif;

    // Find out the number of parameters passed
    num_parms = %parms();
    // If all three parameters were passed, num_parms = 4

    // test if p3 was passed
    if num_parms >= %parmnum(p3);
       // Parameter p3 was passed
       if %addr(p3) <> *null;
          // Parameter p3 was not omitted
       endif;
    endif;
Figure 3. Calling a procedure with the RTNPARM keyword from another language
1. The RPG prototype

D myproc          pr           200a   rtnparm
D   name                        10a   const

2. A CL module calling this RPG procedure

dcl &retval type(*char) len(200)

callprc myproc parm(&retval 'Jack Smith')
Figure 4. Calling a procedure with the RTNPARM keyword written in another language
1. CL procedure GETLIBTEXT

PGM PARM(&retText &lib)

DCL &retText type(*char) len(50)
DCL &lib     type(*char) len(10)

/* Set &retText to the library text */

rtvobjd obj(&lib) objtype(*lib) text(&retText)
return

2. RPG procedure calling this CL procedure using the RTNPARM keyword

D getLibText      pr            50a   rtnparm
D   name                        10a   const
 /free
      if getLibText('MYLIB') = *blanks;
          ...