Tell Me About Your Exports
July 30, 2008 Ted Holt
I ran into an interesting situation recently. I was attempting to tie service program B to existing RPG program A, so that A could use some of the service program B’s routines. Guess what? Program A wouldn’t compile. The experience brings up a good point about procedure prototyping in RPG.
To use a subprocedure requires a procedure prototype. The prototype defines the subprocedure’s interface–the list of parameters, how each parameter is defined, and so forth. RPG programmers commonly use the /COPY and /INCLUDE directives in order to include prototypes in the modules that need them. We have talked about this process before.
If A is to use B’s subprocedures, then, A must have the prototypes of B’s subprocedures. However, A does not have to know about all of B’s subprocedures. The reason my program A wouldn’t compile is that A had too much information about B’s subprocedures.
It turned out that only some of B’s subprocedures were exported. The others were for internal use within module B. However, the copybook contained prototypes for all of B’s subprocedures. A would not compile because it contained a subroutine that had the same name as one of B’s internal (non-exported) subprocedures.
Here, then, is the moral to the story: The copybook for a module should include only prototypes for exported procedures. The prototypes for other procedures should be defined in the module source itself. In this way, other modules will not know about subprocedures that are for internal use only.
Here’s an example. Module B has three subprocedures–Reverse, Proceed, and MoveIt. Two of them–Reverse and Proceed– are exported, so their prototypes are in a copybook called B in source physical file PROTOTYPES. However, the prototype for the MoveIt routine is included in the module’s source code, since MoveIt is for use only within the module.
// *** member B, file QRPGLESRC H option(*srcstmt: *nodebugio) nomain D/copy prototypes,B D MoveIt pr <...code omitted ...> P Reverse b export <...code omitted ...> P Proceed b export <...code omitted ...> P MoveIt b <...code omitted ...>
The copy member–member B in source physical file PROTOTYPES–includes prototypes for Reverse and Proceed only.
// *** member B, file PROTOTYPES D Reverse pr <...code omitted ...> D Proceed pr <...code omitted ...>
Other modules won’t know that B includes a MoveIt subprocedure, therefore they will not choke if they have identifiers (subroutines, variables, etc.) named MoveIt.
When I moved the prototype for the internal subprocedure out of the copybook and into the service program module’s source code, I was able to compile A. Program A is running with B’s subprocedures. Everything is copacetic.