× 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.



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.

This thread ...

Follow-Ups:
Replies:

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.