|
A good explanation, with only one thing, you compile a module with'work'
option 15 in PDM. Buck put all the detail you need in there.
Look how he did it, and just memorize the rule:
ALWAYS add new exported procedures to the very bottom of the list in the
binder source, and REMEMBER to add them to the exported prototypes, and
ALWAYS add any new parameters you're adding to a procedure to the BOTTOM
of the list of parameters and in the code check the number of parameters
before using the new one,
That way you can keep your signature the same and programs that use
"pre-existing" procedures will not break.
For a long time I always copied my list of procedures every time I added
one, and used the *Previous *Current signatures for changes, but then
learned that you could keep the same signature if you did it right.
Saved me a lot of repeated code.
On 2/19/13 4:37 PM, Buck Calabro wrote:
On 2/19/2013 3:44 PM, sjl wrote:
Binding Source, with STRPGMEXP PGMLVL(*PRV) for previous versions ?I used to use *PRV signature blocks, but the practicality of one, never
- sjl
changing, *CURRENT block has won me over.
"RPGLIST" wrote in messageI add new exports to my service programs all the time. Here's how I do
news:mailman.16066.1361306316.10847.rpg400-l@xxxxxxxxxxxx...
Is there an easy way to avoid problems with signatures since we are
supposed to have the ability to add new modules to a service program
that
will not require us to recompile all the objects that depend on that
service program.
it.
My service programs are made up of a single module. In that module are
all the sub-procedures I want that service program to have. Some of
those sub-procedures are intended for public consumption and are
exported from the service program. Some are meant to be internal
afunctions and remain private. The source for that module comes from a
orderpair of source members; the PIs in QRPGLESRC and the PRs in QPROTOSRC.
The QPROTOSRC gets /COPY'd into every source member that needs one of
the public functions. The binder language is stored in another source
file called QSRVSRC. Every one of these source members has the same
name as the module which in turn has the same name as the service
program. There is a binding directory which points to the service
program. It all looks like this:
BUCK *SRVPGM
BUCK *MODULE
BUCK *BNDDIR
To create the module, I use PDM option 14 on QRPGLESRC, member BUCK.
QRPGLESRC mbr(BUCK)
QPROTOSRC mbr(BUCK)
QSRVSRC mbr(BUCK)
I saw a post by Rory Hewitt for a function that returns the procedure
name that fired a trigger. Here's what I do to add it to my service
program:
1) Edit BUCK/QRPGLESRC mbr(BUCK). Add the QWVRCSTK prototype. Internal
to this service program only.
// This /copy goes everywhere I need the PR blocks,
// including this service program
/copy qprotosrc,buck
...
* retrieve job stack
d qwvrcstk PR Extpgm('QWVRCSTK')
d RcvVar 65535a Options(*Varsize)
d RcvVarLen 10i 0 Const
d Format 8a Const
d JobIDInfo 65535a Const Options(*Varsize)
d JobIDFormat 8a Const
d ApiError Like(QUSEC)
...the wrapper for QWVRCSTK. Also private.
// simple QWVRCSTK algorithm, RPG only
d QWVRCSTK0100 pr
d library 10a
d program 10a
d module 10a
d proc 132a
...the implementation of the private wrapper.
p QWVRCSTK0100 b
d QWVRCSTK0100 pi
d library 10a
d program 10a
d module 10a
d proc 132a
...the public interface. It has a decent name and more error handling
than shown here.
p GetProcName b export
d GetProcName pi
d library 10a
d program 10a
d module 10a
d proc 132a
c/free
QWVRCSTK0100(library: program: module: proc);
/end-free
P E
2) Edit BUCK/QPROTOSRC mbr(BUCK). Add the prototype for the public
function.
*=====================================================================
* GetProcName(): Returns the full qualified name of the procedure.
*=====================================================================
d GetProcName PR
d library sp; 10a
d program 10a
d module 10a
d proc 132a
3) Edit BUCK/QSRVSRC mbr(BUCK). Add the new function to the bottom of
the list of exports.
strpgmexp pgmlvl(*current) signature('Buck utilities')
export symbol("CLEANMBRNAME")
export symbol("LSTOBJLCK")
export symbol("SETDBGMODE")
export symbol("SCANCHARBAD")
export symbol(listSplf)
export symbol(lstDBFields)
export symbol(lstDBRecs)
export symbol(getProcName)
endpgmexp
4) CRTSRVPGM SRVPGM(BUCK)
MODULE(*SRVPGM)
EXPORT(*SRCFILE)
SRCFILE(BUCK/QSRVSRC)
SRCMBR(*SRVPGM)
ACTGRP(*CALLER)
The service program has the exact same signature it did before I made
the change. All of the existing callers run just fine because the
sinceof the exports was unchanged. A new one was added to the end, but
functionnone of the existing programs knows about it, they won't be trying to
call it and so cannot fall over.
To use the new function in a program:
1) Edit BUCK/QRPGLESRC mbr(TRIGGER). Add the prototype and the
call.
h bnddir('BUCK')
...
/copy qprotosrc,buck
...
if trgStatus = 'Y';
callp(e) getProcName(callLib: callPgm: callMod: callPrc);
...
2) Compile with PDM option 14.
--buck
--
This is the RPG programming on the IBM i (AS/400 and iSeries) (RPG400-L)
mailing list
To post a message email: RPG400-L@xxxxxxxxxxxx
To subscribe, unsubscribe, or change list options,
visit: http://lists.midrange.com/mailman/listinfo/rpg400-l
or email: RPG400-L-request@xxxxxxxxxxxx
Before posting, please take a moment to review the archives
at http://archive.midrange.com/rpg400-l.
As an Amazon Associate we earn from qualifying purchases.
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.