|
Mike, I did something similar to what Scott's described, except for the following: 1. There is a 'global' array (exported from a 'control' service program) where each array element consists of the procedure name and a procedure pointer to that procedure. The LoadProcs() procedure (the equivalent of Scott's init_plugin()) in each service program (there are currently about 6 service programs in all) is passed the pointer to the array, and it loads its procedures and pointers into the array, e.g.: D ProcArrPtr S * Inz D ProcArr DS Based(ProcArrPtr) D ProcNbr 10I 0 D ProcLookup 10I 0 D 8A D ProcArrElm 48A Dim(100) D ProcName 32A Overlay(ProcArrElm:1) D ProcPtr 16A Overlay(ProcArrElm:33) /free ProcArrPtr = %alloc( %size( ProcArr ) ); ProcArrNbr = 0; // Number of loaded procedures SRVPGM1_LoadProcs(ProcArrPtr); SRVPGM2_LoadProcs(ProcArrPtr); SRVPGM3_LoadProcs(ProcArrPtr); SRVPGM4_LoadProcs(ProcArrPtr); SRVPGM5_LoadProcs(ProcArrPtr); SRVPGM5_LoadProcs(ProcArrPtr); xsort( %addr( ProcArrElm(1) ) : ProcNbr : %size( ProcArrElm ) ); /end-free and in LoadProcs() is code like the following: /free ProcNbr = ProcNbr + 1; ProcName(ProcNbr) = 'PXDLLBRT'; ProcPtr(ProcNbr) = %paddr( PXDLLBRT ); ProcNbr = ProcNbr + 1; ProcName(ProcNbr) = 'PXDLSBRT'; ProcPtr(ProcNbr) = %paddr( PXDLSBRT ); /end-free 2. All the called procedures (except the LoadProcs() procedures) are defined as having 4 parameters - 3 pointers and an error structure. The data that the pointers point will always be the same, e.g.: D Proc@ S * Procptr D Proc PR Extproc(Proc@) D Data1 * Const D Data2 * Const D Control * Const D ApiError Like(QUSEC) The called procedures are all called by name - an array lookup is done on the procedure name, the procedure pointer is set and and the procedure is called. This way there's no need to have a database file - you simply need to add the procedure to the service program and change the LoadProcs() procedure in that service program to load the procedure and its pointer into the array. In the calling program, there is generic code to determine the name of the procedure to call based on various fields, e.g. /free CallProcName = 'PXD' + CustAlpha3 + NbrX1; CallProcPtr = xsearch( CallProcName ); reset QUSEC; CallProc( Data1 : *Null : ControlDS : QUSEC ); /end-free I THINK that it might be possible to call an unexported procedure in a service program this way (if it's exported from the module, that is) - so if a procedure is exported from the module, but it's not included in the binder source, then even though it's not officially accessible from outside the service program, if a procedure inside the service program loads its procedure pointer. I've not tried. However, if it is possible, you could define a service program with only a single exportable procedure (LoadProcs()) and still access all the procedures... Rory
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.