Hi Charles,
You're right. This quote from that thread implies the problem is with
1-byte parameters, but doesn't say exactly what the problem is.
"This is a "feature". Because CL differs from RPG in the way it passes
parameters, you must take explicit action to prevent problems passing
1-byte parameters between CL and RPG when using CallPrc."
Further in the thread, Barbara Morris says
"You can use *CL, *CWIDEN, *CNOWIDEN, *JAVA both for other-language
procedures called by RPG and RPG procedures called by CL, C or Java.
They control the way certain types are returned and passed by value, in
either direction."
which implies it's a difference in the way parameters are passed by
value, but doesn't really clarify.
On another post
(
https://www.ibm.com/mysupport/s/question/0D50z00006LKofY/wrong-value-in-parm-by-value-called-from-cl?language=en_US),
Barbara said
"I know that the system has different ways of handing various data
types passed by
value. I don't know the details, but it looks like zoned and
character are handled differently.
So even though the actual zoned parameters are coming across
correctly, the difference in
handling between zoned and character is affecting the character
parameter following the
zoned parameters."
I was unable to find anything that explained the actual differences in
how the parameters are passed. I wrote a couple of programs to test it.
TESTPARMC (CLLE)
PGM (&FROMRPG)
DCL VAR(&FROMRPG) TYPE(*CHAR) LEN(1)
SNDPGMMSG MSGID(CPF9897) MSGF(QCPFMSG) +
MSGDTA('Received |' *CAT &FROMRPG *CAT +
'|') TOPGMQ(*EXT)
DMPCLPGM
ENDPGM
TESTPARMR (RPGLE)
h option(*nodebugio: *srcstmt)
d TESTPARMC pr extproc('TESTPARMC')
d parm 1a
d TESTPARMI pr extproc('TESTPARMC')
d parm 1n
d TESTPARMCc pr extproc('TESTPARMC')
d parm 1a const
d TESTPARMIc pr extproc('TESTPARMC')
d parm 1n const
d TESTPARMCv pr extproc('TESTPARMC')
d parm 1a value
d TESTPARMIv pr extproc('TESTPARMC')
d parm 1n value
d toCL_char s 1a inz('A')
d toCL_ind s 1n inz('1')
TESTPARMC(toCL_char);
TESTPARMI(toCL_ind);
TESTPARMCc('B');
TESTPARMIc(*off);
TESTPARMCv('C');
TESTPARMIv(*off);
eval *inlr=*on;
CALL TESTPARMR
Received |A|
Received |1|
Received |B|
Received |0|
Received |0|
Received |0|
And from the program dumps:
Variable Type Length Value
Value in Hexadecimal
*...+....1....+....2....+ * . . . + . . . . 1
&FROMRPG *CHAR 1
'A' C1
&FROMRPG *CHAR 1
'1' F1
&FROMRPG *CHAR 1
'B' C2
&FROMRPG *CHAR 1
'0' F0
&FROMRPG *CHAR 1
'0' F0
&FROMRPG *CHAR 1
'0' F0
My understanding is that when RPGLE is passing a parameter by value, it
allocates new storage and makes a copy of the value, and passes a
pointer to that copy. If that were the case, I don't see why it would be
any different than passing a pointer to the defined variable. Maybe it
passes it on the stack instead of a pointer, or in a register or
something, and the CL doesn't look there.
My takeaway is that as long as you're NOT using the CONST or VALUE
keyword on a prototyped parameter that's being passed to a CL, you're
ok. If you use CONST, maybe it works, maybe it doesn't. In my test it
worked, but CONST *might* work the same as VALUE (making a copy of the
value and passing a pointer to that copy) in some cases, so I'm not sure.
--
*Peter Dow* /
Dow Software Services, Inc.
909 793-9050
petercdow@xxxxxxxxx <mailto:petercdow@xxxxxxxxx>
pdow@xxxxxxxxxxxxxx <mailto:pdow@xxxxxxxxxxxxxx>
/
On 8/5/2021 12:58 PM, Charles Wilt wrote:
On Thu, Aug 5, 2021 at 1:51 PM Peter Dow <petercdow@xxxxxxxxx> wrote:
I think this thread covers it:
https://archive.midrange.com/rpg400-l/200209/msg00333.html
Not so much, no details on what's different. As I said originally, just
the "fix".
Charles
As an Amazon Associate we earn from qualifying purchases.