|
Nelson, Well done that man. Peter -----Original Message----- From: Smith, Nelson [mailto:NSmith@lincare.com] Sent: Thursday, December 07, 2000 3:38 AM To: 'RPG400-L@midrange.com' Subject: RE: OO in RPG Jon, In my trigger procedures I use _RSLVSP2 to get a system pointer to a given service program. Then, use that system pointer with QleActBndPgm to activate the service program and get an Activation Mark back (whatever that is....) and then finally, use the activation mark with QleGetExp to get a procedure pointer to the actual procedure name. Once the procedure pointer has been obtained, it can be used in a normal CALLP operation. This was worked out several years ago with a lot of fine help from Barbara. I don't understand all the internals, but it works like a champ and allows me to have completely dynamic triggers controlled by entries in a Database Control file containing the names of the service program and trigger procedure I want to use for any given database file. The database files themselves all have a generic trigger program attached to them which does nothing but call a master procedure which in turn checks the control file for the names and then calls this procedure to obtain a pointer to the actual trigger procedure to be used for that specific file/library combination. This allows tremendous flexibility. For example, different trigger procedures can be used on the same file when it is in different libraries (such as QA vs. Production) and once established, the triggers never have to be added or removed from the base file. All changes can be implemented by changes to the control file or the procedures themselves. For anyone who wishes to try it (including the gentleman), the procedure code follows and again, kudos to Barbara Morris for all of her fine help with the details. I apologize for the spacing, my cut and paste is not the best. P************************************************************************** P RtvProcPtr B EXPORT P************************************************************************** P* P R O C E D U R E P* P* Name.......... RtvProcPtr P* P* Purpose....... To retrieve the address of a procedure exported from P* a service program. P* P* Requires...... The name of the service program, the name of the P* procedure, and optionally, a procedure pointer for P* the return value. P* P* Returns....... A pointer to the procedure as both a return value and P* the optional third parameter (so CALLP may be used). P* P* Service Pgm... Procs_Ptrs P* P* Binding Dir... LinBndDir P* P* Keywords...... Pointer Export Procedure P* P* Sample use.... EVAL pProc = RtvProcPtr(ServicePgm:'Proc_Name') P* or P* CALLP RtvProcPtr(ServicePgm:'Proc_Name':pProc) P* P************************************************************************** D*=================================================================== D* Procedure Initialization: D*==================================================================== D RtvProcPtr PI * PROCPTR D Procedure 30A CONST D SrvPgmName 10A CONST D ReturnPtr * PROCPTR OPTIONS(*NOPASS) D*=================================================================== D*==================================================================== D* Data Structure to set object data: D*==================================================================== D ObjectDS DS D ObjectType 2A INZ(X'0203') D ObjectName 30A D ObjReqAuth 2A INZ(X'0000') D*==================================================================== D*==================================================================== D* Standalone fields: D*==================================================================== D SystemPtr S * PROCPTR D ProcedurePtr S * PROCPTR D ActivationMark S 10I 0 INZ( 0 ) D ProcName S 30A INZ( *BLANKS ) D ProcNameLen S 10I 0 INZ( 0 ) D*==================================================================== C************************************************************************** C* M A I N L I N E C************************************************************************** * Get system pointer to the service program: C EVAL ObjectName = SrvPgmName C CALLB '_RSLVSP2' C PARM SystemPtr C PARM ObjectDS * Then, activate the service program & get an activation mark back: C CALLB 'QleActBndPgm' C PARM SystemPtr C PARM ActivationMark C PARM *OMIT C PARM *OMIT C PARM *OMIT * Then, get a pointer to the procedure: C EVAL ProcName = Procedure C ' ' CHECKR ProcName ProcNameLen C CALLB 'QleGetExp' C PARM ActivationMark C PARM *OMIT C PARM ProcNameLen C PARM ProcName C PARM ProcedurePtr C PARM *OMIT C PARM *OMIT * Load up the return pointer if it was included in the parameters: C IF %PARMS = 3 C EVAL ReturnPtr = ProcedurePtr C ENDIF C RETURN ProcedurePtr C************************************************************************** C* E N D O F M A I N L I N E * C************************************************************************** P RtvProcPtr E P************************************************************************** Jon, to persue your idea of a program that loads an array of procedure pointers, do you know of a way to obtain a list of pointers to all of the service program's exports at once, rather than just the named ones as in the procedure shown above or would I have to first create a list of the exported procedure names and get the pointers one-by-one? Also, how would you know what parameters are required with different procedure pointers in the array when you go to use them? In the case of my triggers above, they all have the same parameter requirements, so it is not a problem. > -----Original Message----- > From: Jon.Paris@hal.it [SMTP:Jon.Paris@hal.it] > Sent: Tuesday, December 05, 2000 11:33 AM > To: RPG400-L@midrange.com > Subject: RE: OO in RPG > > > >> To obtain a truly dynamic procedure call that is not known at compile > time > you must you the special API's that permit you to force the activation of > a > service pgm and provide access to the procedures within. > > Hi Peter, > > one qualification and one question. > > While it is true that the addresses must be known at compile time, it is > _which_ program's compile time that is the issue. For example, I can > create a dynamically called program which establishes procedure pointers > for all of the procedures it wishes to make available to the outside > world. > > This program has a mainline whose only purpose is to return to its caller > an array of procedure pointers and their names. This program can be > dynamically called during the initialization phase. Subsequently the > procedure pointers are used to call the subprocedures in the "program". > > By doing it this way the only program that needs to know the procedure > addresses at compile time is the one that contains them - not exactly an > arduous limitation!! The other benefit is that the program itself is > dynamically called to provide the pointers in the first place and because > it is a dynamic call it can be called by variable name. Since it is only > ever called once during the currency of the application, the performance > of > such a call is not an issue - of course it mustn't return with LR on > <grin>. > > As you can see considerable flexibility can be gained without the need to > resort to the APIs. > > That brings me to my question. Which are the APIs involved? I tried to > find them the other day to answer a question from a "gentleman" on one of > the lists who insisted that I was lying when I said it could be done. > Because he'd been so darn rude I didn't put a lot of work into it, but I > know they exist. Can you help me out with the names? > > Thanks muchly > > > +--- > | This is the RPG/400 Mailing List! > | To submit a new message, send your mail to RPG400-L@midrange.com. > | To subscribe to this list send email to RPG400-L-SUB@midrange.com. > | To unsubscribe from this list send email to RPG400-L-UNSUB@midrange.com. > | Questions should be directed to the list owner/operator: > david@midrange.com > +--- **************************************************************************** **************************************************************************** **************************************************** This message originates from Lincare Holdings Inc. It contains information which maybe confidential or privileged and is intended only for the individual or entity named above. It is prohibited for anyone else to disclose, copy, distribute or use the contents of this message. All personal messages express views solely of the sender, which are not to be attributed to Lincare Holdings Inc., and may not be copied or distributed without this disclaimer. If you received this message in error, please notify us immediately at MailAdmin@lincare.com or (800) 284-2006. **************************************************************************** **************************************************************************** **************************************************** +--- | This is the RPG/400 Mailing List! | To submit a new message, send your mail to RPG400-L@midrange.com. | To subscribe to this list send email to RPG400-L-SUB@midrange.com. | To unsubscribe from this list send email to RPG400-L-UNSUB@midrange.com. | Questions should be directed to the list owner/operator: david@midrange.com +--- This communication is confidential and may be legally privileged. If it is not addressed to you, you are on notice of its status. Please immediately contact us at our cost and destroy it. Please do not use, disclose, copy, distribute or retain any of it without our authority - to do so could be a breach of confidence. Thank you for your co-operation. Please contact us on (09) 356 5800 if you need assistance. +--- | This is the RPG/400 Mailing List! | To submit a new message, send your mail to RPG400-L@midrange.com. | To subscribe to this list send email to RPG400-L-SUB@midrange.com. | To unsubscribe from this list send email to RPG400-L-UNSUB@midrange.com. | Questions should be directed to the list owner/operator: david@midrange.com +---
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.