Hi Doug,
QPMLPMGT became available in V5R3, yet I must still support customers
on releases prior to that.
When my customer on V5R2 attempts to run this program, they receive:
CPD0192: Service program QPMLPMGT not found.
I can think of three ways to solve this problem. These are alternatives
to one another, you don't need to do them all:
IF DEFINED ALTERNATIVE
-----------------------
One simple approach is to use /if defined in the source code, and
compile the code separately for V5R2 vs V5R3. It's a pain in the butt to
do a different build for different releases, but it should work. For
example:
/if defined(*V5R3M0)
D GetLparInfo PR 10I 0 EXTPROC('dlpar_get_info')
D Receiver 344
D Format 10I 0 Value
D RcvrLen 10I 0 Value
MONITOR;
RtnValue = GetLparInfo(Receiver:Format:RcvrLen);
ON-ERROR;
RtnValue = 0;
ENDMON;
/else
RtnValue = 0;
/endif
When compiled with a V5R3 or later compiler, this code will compile in
the call to GetLparInfo. when compiled on a V5R2 compiler (including
TGTRLS(V5R2M0)) this code will simply set RtnValue to 0, and not try to
call the routine.
*PGM WRAPPER ALTERNATIVE
------------------------
Another relatively simple solution is to create a *PGM object (as
opposed to a *SRVPGM) that takes parameters for the API, calls it, and
returns the result. For example, write the following standalone RPG
program:
H DFTACTGRP(*NO)
D LPARINFO PR ExtPgm('LPARINFO')
D Receiver 65535a options(*varsize)
D Format 10i 0 const
D RcvrLen 10i 0 const
D RtnValue 10i 0
D LPARINFO PI
D Receiver 65535a options(*varsize)
D Format 10i 0 const
D RcvrLen 10i 0 const
D RtnValue 10i 0
D GetLparInfo PR 10I 0 EXTPROC('dlpar_get_info')
D Receiver 65535a options(*varsize)
D Format 10I 0 Value
D RcvrLen 10I 0 Value
/free
MONITOR;
RtnValue = GetLparInfo(Receiver:Format:RcvrLen);
ON-ERROR;
RtnValue = 0;
ENDMON;
return;
/end-free
Then have the caller do something like this:
if release >= 'V5R3M0';
LPARINFO( MyRcvr
: MyFmt
: %size(MyRcvr)
: RetVal );
endif;
Since the *PGM wrapper is never called on earlier releases, you won't
have a problem...
DYNAMIC *SRVPGM BINDING
------------------------
Finally... if you really want to do what you suggested, and dynamically
call the API, you CAN do so, but it'll involve manually resolving the
service program, manually activating it, manually getting a pointer to
it's exported procedure, and finally, calling it. This involves:
a) Call the QLICVTTP API to get the hex object type for a *SRVPGM.
b) Call the RSLVSP2 MI builtin to resolve a system pointer to the
*SRVPGM object. In RPG, you can define your system pointer as a procptr.
c) Call the QleActBndPgm() API to activate the service program.
d) Call the QleGetExp() API to get a procedure pointer to the
dlpar_get_info() procedure within the service program.
e) Call your GetLparInfo prototype, but have the Extproc() point to the
procedure pointer.
That type of coding is not for the feint-of-heart... I'm not sure that
I'd recommend it, since I'm not sure that it'll provide any benefits
above and beyond the simpler methods I mentioned above. But it's pretty
cool that it's possible :)
As an Amazon Associate we earn from qualifying purchases.