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
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.