Hello,
Yes, it is possible to call any program with any number of parameters,
including pointers.
This is how you do it:
First, prototype the machine instruction, CALLPGMV:
D callProgram PR extproc('_CALLPGMV')
D programAddress...
D * procptr const
D argVector * value
D argCount 10U 0 value
Then, create this function:
//
=======================================================================
// Function getProgramAddress:
//
=======================================================================
// This function returns the system address of a program object or
*null
// if not found or error occurs.
//
=======================================================================
P getProgramAddress...
P B
D PI * procptr
D inProgramName...
D 10A const
D inProgramLibrary...
D 10A const
D options(*nopass)
//
=======================================================================
// - Local Data Types -
//
=======================================================================
D ErrorCode DS
D BytesProvide 10I 0 Inz(%Size(ErrorCode))
D BytesAvail 10I 0
D ExceptID 7
D Reserved 1
D ExceptData 240
D typeSystemPointer...
D S * procptr based(@)
//
=======================================================================
// - External Procedure Prototypes -
//
=======================================================================
D resolveUnqualifiedSystemPointer...
D PR extproc('_RSLVSP2')
D systemPointer like(typeSystemPointer)
D resolution like(resolutionTemplate) const
D resolveQualifiedSystemPointer...
D PR extproc('_RSLVSP4')
D systemPointer like(typeSystemPointer)
D resolution like(resolutionTemplate) const
D libraryPointer...
D like(typeSystemPointer) const
//
=======================================================================
// - Local Data Structures -
//
=======================================================================
D resolutionTemplate...
D DS qualified
D typeCode 1A
D subtypeCode 1A
D objectName 30A
D authority 2A inz(x'0000')
D activationInformation...
D DS qualified align
D bytesReturned 10I 0 inz(%size(activationInformation))
D bytesAvailable...
D 10I 0 inz
D 8A inz(*allx'00')
RESERVED
D activationGroupMark...
D 10I 0
D activationMark...
D 10I 0
D 7A inz(*allx'00')
RESERVED
D flags 1A
D 1A inz(*allx'00')
RESERVED
//
=======================================================================
// - Local Constants -
//
=======================================================================
// return codes for exportTypeFound parameter for getExport procedure
D EXPORT_TYPE_NOT_FOUND...
D C 0
D EXPORT_TYPE_PROCEDURE_FOUND...
D C 1
D EXPORT_TYPE_DATA_FOUND...
D C 2
D EXPORT_TYPE_NOT_ACCESSIBLE...
D C 3
//
=======================================================================
// - Local Procedure Parameter Variables -
//
=======================================================================
D lProgramLibrary...
D S like(inProgramLibrary)
D inz('*LIBL')
//
=======================================================================
// - Local Variables -
//
=======================================================================
D serviceProgramProcedureNameLength...
D S 10I 0 inz
D libraryPointer S like(typeSystemPointer)
D serviceProgramPointer...
D S like(typeSystemPointer)
D activationMark S 10I 0 inz
D procedurePointer...
D S * procptr inz(*null)
D exportTypeFound...
D S 10I 0 inz(EXPORT_TYPE_NOT_FOUND)
/free
monitor;
// Get the program library - if it is not passed, *LIBL is
// used.
if %parms >= 2;
lProgramLibrary = inProgramLibrary;
endif;
//
-------------------------------------------------------------------
// Get the pointer to the service program
//
-------------------------------------------------------------------
// If library is generic *LIBL (only generic allowed)
----------------
if lProgramLibrary = '*LIBL';
// Obtain pointer to service program procedure without context
----
resolutionTemplate.typeCode = x'02'; // program
resolutionTemplate.subtypeCode = x'01';
resolutionTemplate.objectName = inProgramName;
resolveUnqualifiedSystemPointer
(serviceProgramPointer : resolutionTemplate);
else;
// Obtain pointer to library
--------------------------------------
resolutionTemplate.typeCode = x'04'; // context
resolutionTemplate.subtypeCode = x'01'; // access
group
resolutionTemplate.objectName = lProgramLibrary;
resolveUnqualifiedSystemPointer
(libraryPointer : resolutionTemplate);
// Obtain pointer to service program procedure with context
-------
resolutionTemplate.typeCode = x'02'; // program
resolutionTemplate.subtypeCode = x'01'; // module
resolutionTemplate.objectName = inProgramName;
resolveQualifiedSystemPointer
(serviceProgramPointer : resolutionTemplate :
libraryPointer);
endif;
return serviceProgramPointer;
on-error *all;
return *null;
endmon;
/end-free
P getProgramAddress...
P E
Then, you obtain the system address of your program via the
getProgramAddress function:
D programAddress S * procptr
programAddress =
getProgramAddress
('PROGRAMA');
Next, setup your parameter argument:
D argVector S * dim(399) based(argVector__)
D argCount S 10U 0 inz
argCount = 3; // example
// set addresses of arguments
argVector(1) = %alloc(%size(arg1)); // example
argVector(2) = %alloc(%size(arg2));
argVector(3) = %alloc(%size(arg3));
Then, copy the memory to the arguments using MEMCPY:
D memcpy PR extproc('__memcpy')
D target * value
D source * value
D bytes 10U 0 value
memcpy // example
(argVector(1) :
%addr(arg1) :
%size(arg1));
Finally, make your call:
callProgram(programAddress : argVector__ : argCount);
dealloc(en) argVector__;
Have fun!!!
Kind regards,
Michael P. Scott
Programmer Analyst II | Merch-Setup Engineer Liaison
-----Original Message-----
From: rpg400-l-bounces@xxxxxxxxxxxx
[mailto:rpg400-l-bounces@xxxxxxxxxxxx] On Behalf Of Scott Klement
Sent: Wednesday, July 08, 2009 10:06 AM
To: RPG programming on the IBM i / System i
Subject: Re: Passing a pointer between programs when using a dynamic
call
Hi Stefan,
Is it possible to use a pointer as a parameter when calling another
program?
The program call has to be made up dynamically and executed using
qcmdexec or system API...
You have two questions here, I think. Is it possible to pass a pointer
as a parameter when calling a program? Yes! Provided that you are
doing a direct program-to-program call.
Is it possible to pass a pointer via QCMDEXC or system()? No.
Remember, QCMDEXC (and similar tools) receive one big character string
from your program, and they interpret the contents of that character
string, via scanning/parsing techniques. You can't pass any sort of
variable (including a pointer, which is after all, a variable) when
using those tools.
Program B gets invoked and need a mechanism to send back information
to program A.
Then you don't want to use QCMDEXC or it's friends.
Just to hide the complexity of the datastructure in program A my
thought was to create a service program ( program C ) with procedures
that can be called by program B. It then seems reasonably that a
pointer must be used to "connect" the procedures in pgm C with the
datastructure in pgm A. Along the run it might be needed for program C
to change pointers in pgm A datastructure ( realloc of memory ).
I don't really understand this part of your message at all.
1) Why does PROGRAM A work this way? Why do you need so much
flexibility in terms of the parameter list? Do you work for a software
house where your software has to be able to call a customer's program
with any arbitrary parameter list? I can't think of any other reason
someone would do something like this.
2) I don't understand the "Program C" business at all. If you're
passing the data via a parameter, how does a service program help? Why
not pass the data via the service program instead of the parameter list?
3) Why does a pointer need to be used to "connect" your programs?
Am I out on very thin ice here? Better solutions?
Hard to say. I think we need more information to even begin to give you
advice. Speaking for myself, at least, I really don't understand your
scenario.
--
This is the RPG programming on the IBM i / System i (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.