0

Does anyone know how to call a internal described sub-procedure returning a value using a procedurepointer.

I was reading the ILE RPG manual and got stuck on %PADDR BIF that allows me to get the address of a procedure. For instance when having dynamically decide which procdure I want to call, I can either doing it with if...then...else..endif and CALLP. But is there a way to externalise the callp out of the if structure? Like delegates in .NET where I can define a delegate and assign the function/sub to call within a control structure.

What I know is how to define the PROCPTR and how to call a procedure WITHOUT a return value. But what do I have to do when dealing WITH return values.

Here is a sample of assigning the procedure adresses and calling the procedures itselfe:

 H**************************************************************************
 H DEBUG DECEDIT('0,') DATEDIT(*DMY.) dftactgrp(*no)
 H*
 D**************************************************************************
 D*  Prototypes
 D*-------------------------------------------------------------------------
 D*            -------------------------------------------------------------
 D*            Returns String 1
 D*            -------------------------------------------------------------
 D GetStr1         pr            10a
 D
 D*            -------------------------------------------------------------
 D*            Returns String 2
 D*            -------------------------------------------------------------
 D GetStr2         pr            10a
 D
 D**************************************************************************
 D*  Definitions
 D*-------------------------------------------------------------------------
 D pPtrGetStr1     s               *   procptr
 D pPtrGetSTr2     s               *   procptr
 D string1         s             10a
 D string2         s             10a
 D
 C**************************************************************************
 C*  M A I N P R O G R A M 
 C**************************************************************************
 C
 C                   eval      pPtrGetStr1 = %paddr(GetStr1)
 C                   eval      pPtrGetStr2 = %paddr(GetStr2)
 C
 C                   eval      string1 = GetStr1()
 C                   eval      string2 = GetStr2()
 C
 C     string1       dsply
 C     string2       dsply
 C
 C                   move      *on           *inlr
 P**************************************************************************
 P*  P R O C E D U R E S
 P**************************************************************************
 P*            -------------------------------------------------------------
 P*            Returns String 1
 P*            -------------------------------------------------------------
 P GetStr1         b
 D GetStr1         pi            10a
 D result          s             10a
 C                   movel     'string1'     result
 C                   return    result
 P GetStr1         e
 P
 P*            -------------------------------------------------------------
 P*            Returns String 2
 P*            -------------------------------------------------------------
 P GetStr2         b
 D GetStr2         pi            10a
 D result          s             10a
 C                   movel     'string2'     result
 C                   return    result
 P GetStr2         e
 P************************************************************************** 

Thanks in advance

Radinator
  • 1,048
  • 18
  • 58
  • This might be the kind of thing you want to do: https://stackoverflow.com/a/49656206/3175562 – Mike Apr 04 '18 at 17:48

1 Answers1

7

Almost there:

You need a prototype that uses the procedure pointer to resolve the dynamic procedure.

dcl-s pDynamicProc      Pointer(*proc);                 // --2--
dcl-pr DynamicProc      Char(25) ExtProc(pDynamicProc); // --1--
  parm1                 Char(10);
  parm2                 Char(10);
end-pr;

...

// Before you call it you need to set the pointer
if (some condition) then;                 // --3--
  pDynamicProc = %paddr(Proc1);
else;
  pDynamicProc = %paddr(Proc2);
endif;

// Here is the call
MyVariable = DynamicProc(p1: p2);         // --4--

...

// ====================================================
// Procedure definitions
dcl-proc Proc1;
  dcl-pi *n Char(25);
    parm1       Char(10);
    parm2       Char(10);
  end-pi;

// Do something

end-proc;

// ====================================================
// Another procedure with the same procedure interface
dcl-proc Proc2;
  dcl-pi *n Char(25);
    parm1       Char(10);
    parm2       Char(10);
  end-pi;

// Do something else

end-proc;

Just so you don't have to search through the code to determine what is happening. DynamicProc is a procedure that is resolved by procedure pointer pDynamicProc. The prototype is found at // --1--. The ExtProc() keyword specifies a procedure pointer instead of a procedure name. The pointer is defined at // --2--. Before you can call a procedure with DynamicProc you must populate the pointer with a procedure address. This happens at // --3--. Now you can call DynamicProc just as if it were any other procedure (see // --4--).

Notice that I don't have prototypes for Proc1 and Proc2. I don't need those unless I am calling them directly from outside the module. BTW, based on earlier questions, you are on a release that supports omitting the prototype for internal procedures. You should stop coding fixed format RPG. Those who follow after you to maintain your code will thank you.

jmarkmurphy
  • 11,030
  • 31
  • 59