I'm trying to get experience in RPGLE and IBM i stuff and constantly learning. Since most code in the wild seems to be classic positional, I'll stick with this to get used to it. So I would rather not use /free — /end-free stuff. Incidentally, I'm doing this on an old 9401-150 with only V4R5.TL;DR: How can I get a return value back from an external called ILE program (with it's own MAIN section, that is, it's standalone in itself) in it's own activation group (.NEW) to the callee?I have a subfile program ready and running fine. I want to call an external program to handle requests by OPT value in the subfile. So I defined a PR in the D-Specs of the callee: DROEDETPG PR EXTPGM('ROEDETPG')DCMODE LIKE(MODE)DCTYP LIKE(TYP)Later, I call the Program which also works fine.
As the input parameter is passed by value I have to move its value to my data structure, line 14, before I can update the subfields, lines 16 – 16. I return the data structure on line 17, and end the procedure on line 18. A fixed format version of this code can be seen at the bottom of this post here. What of the binding directory?
C SELECTC OPT WHENEQ '2'C MOVE 'CHG' MODEC CALLP ROEDETPG(MODE:TYP)C ENDSLThis is the entry point in the called program: C.ENTRY PLISTC PARM CMODE 3C PARM CTYP 16Now, maybe the record I want to change is already locked. So, I'm using CHAIN(E) in the external program and get%STATUS from the PF after the CHAIN. The status value for that is 1218 and I want to get this value back to the calling program, so it may use the message line to tell the user, the record is locked and unavailable at the moment.All I could find online is to prototype the call and define a call interface (PI) which is possibly applicable to procedures only.So I thought of a 'temp file' as I'm used to in Bash and C on Unix/Linux for that purpose. There seems to be no mktemp equivalent, but I can create files with the same name in QTEMP. This applies to a file type.DTAARA.
Unfortunately (expectable?) this file is visible only to the calling program. Maybe could create a global keyed.DTAQ with SENDERID(.YES) but maybe this is overkill?Why don't I put the functionality in the external program into a bunch of functions and use CALLP? Well, I'm still learning. I decided to move stuff from Subroutines out of the main source to end the constant hassle with state changes involved when subroutines do stuff. When a SR does a READ, the database pointer points to another record which brings a multitude of erratic behavior when continuing the subfile stuff.Plus, global variables (field content) get overwritten which adds more code to move content aside, save the key value for the DB, call the SR and restore variables again and do a SETLL to get back to the state where I was before. I expect this to be easier but maybe I'm still too much a rookie regarding ile rpg.I'm open for other suggestions regarding how to avoid my underlying problem (file pointer and global vars) properly. Mostly to discourage new posters who, consciously or otherwise, attempt to transfer their sense of urgency or desperation onto volunteers.
We get a lot of really crass begging here, and the community takes a dim view of it, because volunteers only have so much energy, and they do not need to see any form of persuasion to take on more help than they genuinely have time for. In any case, notes about how important/urgent something is is immaterial for future readers, so it is trimmed also because it adds no extra value to the post.–Aug 9 '18 at 22:42. Because parameters in ILE are passed by reference, one easy way to get one or more return values back from an external program is to just define them in your prototype and your called programs parameters.
Coming from other programming environments, this is a little strange to me as I have been brainwashed into BYVAL not BYREF for so many years now, but really that is all a function return value ever is, a value on the stack that gets passed back to the caller. Some languages would define these as out parameters, but they are actually inout that you are treating like an out. DROEDETPG PR EXTPGM('ROEDETPG')DCMODE LIKE(MODE)DCTYP LIKE(TYP)DCERR 7C.ENTRY PLISTC PARM CMODE 3C PARM CTYP 16C PARM CERR 7One advantage to this method is that rather than return one value as RPGLE subprocedures do and functions do in most programming languages, you can return as many values as you need for a given task without defining a data structure to hold them all in.QTEMP is a great library to use, but I think creating a file is overkill for what can be done with simple parameter passing. I do think you may have some misconceptions about QTEMP, though.
It is defined on a per-job basis, so if you write something there (in a file or in a userspace object, which can be more convenient than a file if you are comfortable with pointers), it will absolutely be there for other programs running in that job to find until the job ends or it is explicitly deleted. Experiment a little to confirm this, and if necessary ask a separate question, because it really should be able to be used as shared storage for multiple programs. I know you said no /free or.FREE but I'm going to ignore that because as far as I'm concerned, the fixed format stuff can go burn in the hellfire from whence it was spawned.
You are welcome to translate the following code back to fixed format on your own. In order to properly do this, you should simply be passing in a variable to the program that will contain the error.MYPGM.RPGLE.FREE/Include MYHDRDcl-Pi.N;ErrorRet Char(7); // or whatever type you want to returnEnd-Pi;ErrorRet = 'RFE1234';.InLR =.On;Return;MYHDR.RPGLE.FREEDcl-Pr MyPgm ExtPgm('MYPGM');ErrorRet Char(7); // or whatever type you want to returnEnd-Pr;CALLINGPGM.RPGLE.FREE/Include MYHDRDcl-S Error Char(7) Inz;MyPgm(Error);// Error should now contain 'RFE1234'.
Well, your first issue is the age of your OS. If you were on a more modern platform, you could create a subprocedure with local file descriptions, and be rid of the file pointer issues like this: dcl-proc myFileIsLocked;dcl-pi.n Ind;mode Char(3) const;type Char(16) const;end-pi;dcl-f myfile keyed usage(.Update);dcl-c RECORDLOCKED 1218;chain(e) (type) myfile;return (%status = RECORDLOCKED);end-proc;However, even at v4r5, you can use a sub-procedure to accomplish your goal. Put your procedure in a service program, and define the file in the global area of the module.
My previous post explained why the value was always the same but not why it was 0x00. The hex value of '0' is actualy 0xF0.
The only thing I can think of is that the 0 didn't have quotes round it?Actually it didn't explain it at all.The reason for the hex 00 is that C always widens single byte return values to two bytes. The 'real' return value being in the second byte. Stupid - but that's C for you. CL adopted the same idiot notion - RPG did it 'right' but has had to add a compiler option to facilitate reurning a single character to a C or CL function. Can't recall what it is and on a dial-up link I don't think I'll try to find it!Anyway - expand the RPG to look for two charcaters (and then discard the first) or use the compatibility keyword on the prototype.Jon (If I was any more p.ssed with Bell Canada I'd burst) Paris.
Whats up with bell Canada?They disconnected my DSL line 'by accident' 5 weeks ago and cannot reconnect me because the switch controlling my area has reached capacity. Understand that it has taken over 4 weeks for me to find that out.
Because I travel a lot it is only when returning home that I find that the previous 'fix' attempt failed - and of course the business office is only open Monday - Friday so another week goes by.Finally found the executive office help desk and at least know what's going on now but.