× The internal search function is temporarily non-functional. The current search engine is no longer viable and we are researching alternatives.
As a stop gap measure, we are using Google's custom search engine service.
If you know of an easy to use, open source, search engine ... please contact support@midrange.com.




OK, I know this has been discussed in the past and I've read Barbara's document on "Converting from C Prototypes to IBM RPG/400 Prototypes" at:

http://www-01.ibm.com/support/docview.wss?uid=nas16e4fc64bf5995b8886256b730054c832

and various other places on the 'net (mostly with no attribution ... tsk, tsk).

I note that the primary focus is on passing parameters and very little is said about receiving a return value. I want to get a 1-byte value back from C but C seems to always widen no matter what I do. My question relates to the following line in Barbara's document:

:quote.
Note: If the C function is specified #pragma argument(nowiden) for the function, you should use EXTPROC(*CNOWIDEN). Coding *CNOWIDEN is necessary for RPG to handle 1C and 1A correctly, when passed by value or returned.
:equote.

My confusion stems from the fact that if C is instructed to not widen then why does RPG need *CNOWIDEN when that's RPG's default behaviour? What is RPG doing that requires it to be *instructed* to behave differently?

Here's some test code:

C module:
char inttochar( int i )
{
char c = i;
return c;
}

RPG module:
H OPTION(*SRCSTMT : *NODEBUGIO)
H BNDDIR('QC2LE')
D inttochar PR 1 EXTPROC('inttochar')
D int 10I 0 VALUE
D toHex PR EXTPROC('cvthc')
D hex 32766A OPTIONS(*VARSIZE)
D char 16383A CONST OPTIONS(*VARSIZE)
D len 10I 0 VALUE
D msgText S 52
D compileFlagsInt...
D S 10U 0 INZ(X'00000075')
D compileFlags S 1
D compileFlagsHex...
D S 2
C EVAL compileFlags = inttochar( compileFlagsInt )
C CALLP toHex( compileFlagsHex : compileFlags :
C %SIZE(compileFlags)*2 )
C EVAL msgText = '0x' + compileFlagsHex
C msgText DSPLY
C SETON LR
C RETURN

Running this code and stepping into inttochar() shows i contains X'00000075' and c contains x'75'. So far so good. Returning to the RPG shows compileFlags contains X'00' which is to be expected if a mismatch in interpretation occurs (i.e., C sticks the value in the rightmost byte of a 4-byte integer--widened--and RPG only looks at the leftmost byte).

So to "correct" RPG's behaviour I need to either specify *CWIDEN (to match C's default behaviour) or code the C function with #pragma nowiden and specify *CNOWIDEN in RPG. So to test things I add:

D inttochar PR 1 EXTPROC(*CWIDEN : 'inttochar')

and then when I run the program I see compileFlags contains X'75' exactly as expected and desired. However, I should be able to make *CNOWIDEN work as long as both C and RPG have the same view of the world. So I code:

D inttochar PR 1 EXTPROC(*CNOWIDEN : 'inttochar')

in the RPG and add:

#pragma argument ( inttochar, nowiden )

to the C source (before the function definition). When I run the program I see compileFlags contains X'75' exactly as expected and desired.

Referring to the C/C++ Compiler Reference I see that the documentation for #pragma argument says:

nowiden Specifies that the arguments are not widened before they are passed or received.

Although this implies that it applies only to arguments and not return values I wonder whether that's true because there seems little point in supporting a mechanism to match parameters/arguments and not support matching the return value. (However, I would not be surprised to learn this is yet another example of ridiculous behaviour in C.)

If that's true then because RPG's default behaviour is to presume no widening then I should be able to specify no widening in the C function and leave RPG at the default so I remove *CNOWIDEN from the RPG prototype. When I run the program I see compileFlags contains X'00' so we're back to the widening problem.

This supports my presumption that C always widens the return value so I wonder what happens if I remove #pragma nowiden from the C function and tell RPG that *CNOWIDEN is actually in effect. I make those changes and now when I run the program I see compileFlags contains X'75'. Curiouser and curiouser.

So although C always widens the return value telling RPG that it's not widened makes things work. Why is that so? Is it because RPG is being warned that a C function is being called, it knows the C function will always widen the return value, and so it adjusts which bytes of the return value it uses according to the size and type of the variable specified on the left-hand side of the assignment?

My conclusion is that unless I specify either *CWIDEN or *CNOWIDEN I cannot make C and RPG behave properly and since I have other reasons for not using those my only option is to write a conversion routine in a language other than C (e.g., RPG) to convert the int returned by C into a 1-byte char for use by RPG or COBOL.

Can anyone (hello Barbara) confirm this?


Finally, Barbara's document shows that a C programmer can tell the compiler not to widen by specifying:

#pragma nowiden(fn)

but that's syntactically incorrect. It probably should be one of:

#pragma argument (fn, [type,] nowiden )
or
#pragma linkage (fn, [type,] nowiden )


Regards,
Simon Coulter.
--------------------------------------------------------------------
FlyByNight Software OS/400, i5/OS Technical Specialists

http://www.flybynight.com.au/
Phone: +61 2 6657 8251 Mobile: +61 0411 091 400 /"\
Fax: +61 2 6657 8251 \ /
X
ASCII Ribbon campaign against HTML E-Mail / \
--------------------------------------------------------------------




As an Amazon Associate we earn from qualifying purchases.

This thread ...

Follow-Ups:

Follow On AppleNews
Return to Archive home page | Return to MIDRANGE.COM home page

This mailing list archive is Copyright 1997-2024 by midrange.com and David Gibbs as a compilation work. Use of the archive is restricted to research of a business or technical nature. Any other uses are prohibited. Full details are available on our policy page. If you have questions about this, please contact [javascript protected email address].

Operating expenses for this site are earned using the Amazon Associate program and Google Adsense.