Loading and dropping DLL functions is global for all REXX programs! Therefore you should avoid using RxFuncDrop or any DLL specific unload routine for general REXX DLLs like REXXUTIL.
To make your REXX programs resident against other programs dropping DLL functions you can use one of three methods. Each method has its advantages and disadvantages. You may use the one you like best.
Method 1.
Load the necessary functions with REXX names other than their normal REXX
names. In this case you should unload the functions at program end.
(see Loading more than one DLL
with the same function names for an example)
Method 2.
Redefine the necessary functions in your program. Add code to load the DLL
routine again if it was dropped to the new function in your program (see
Redefinition of functions from
a DLL and method 3 below for an example)
Method 3.
Use a general wrapper function to call the functions from the DLL. Example:
/* ------------------------------------------------------------------ */ /* sample code to check the REXXUITL wrapper */ /* */ /* Note: start REXXTRY in another session and do a SysDropFuncs in */ /* that session while running this program. */ /* To use the wrapper routine for more than one DLL you can add */ /* another parameter for the name of the DLL. */ /* */ /* install a handler for CTRL-BREAK */ SIGNAL ON HALT NAME ProgramEnd do forever say say "Example for using the REXXUTIL wrapper" say say "Start another session and drop the REXXUTIL functions to" say "see how it works ..." say say "Press CTRL-BREAK to halt this program ..." say say "Now calling some REXXUTIL functions using the wrapper ..." say say " Calling SysOs2Ver -> OS/2 Version is " || , REXXUTIL( "SysOS2Ver" ) say " Calling SysTextScreenSize -> TextscreenSize is " || , REXXUTIL( "SysTextScreenSize" ) say " Calling SysFileTree -> result is " || , REXXUTIL( "SysFileTree", "*.CMD", "fileStem" ) /* show the results of the SysFileTree function */ say " SysFileTree founds " || fileStem.0 || " files:" do i = 1 to fileStem.0 say " " || i || ". entry is " || , Word( fileStem.i, words( fileStem.i ) ) end /* do i = 1 to fileStem.0 */ say "Result of calling the invalid function SysFoo is " || , REXXUTIL( "SysFoo" ) say "Now sleeping for 2 seconds" call REXXUTIL "SysSleep", 2 end /* do forever */ ProgramEnd: exit /* ------------------------------------------------------------------ */ /* function: call a function from the DLL REXXUTIL. Reload the */ /* REXXUTIL function if it is not loaded or dropped by */ /* another process. */ /* */ /* call: REXXUTIL funcName {, funcParameter} {...} */ /* */ /* where: funcName - name of one of the REXXUTIL functions */ /* funcParameter - parameters for the function (if any) */ /* */ /* returns: SYNTAX ERROR # */ /* if a syntax error occurred, # is the error number */ /* (999 = parameter funcName missing) */ /* else the return code of the REXXUTIL function */ /* */ /* */ /* notes: Do not use PROCEDURE for this routine! */ /* */ REXXUTIL: /* get the function name */ rx.__funcName = strip( arg(1) ) /* check the parameter */ rc = "SYNTAX ERROR 999" if rx.__funcName = "" then SIGNAL rx.__REXXUtilEnd /* install a local error handler */ SIGNAL ON SYNTAX Name rx.__ReloadREXXUtil /* create the statement to execute */ rx.__iLine = "rx.__fRC = " rx.__funcName rx.__iLine = rx.__iLine || "(" do i = 2 to arg() if i <> 2 then rx.__iLine = rx.__iLine || ", " rx.__iLine = rx.__iLine || '"' || arg(i) || '"' end /* do i = 2 to arg() */ rx.__iLine = rx.__iLine || ")" rc = 0 /* if rc is not equal zero after the interpret */ /* instruction there was an error */ /* call the REXXUTIL function */ interpret rx.__iLine rx.__ReloadREXXUtil: /* check the result */ if rc = 0 then do /* execution okay */ rc = rx.__fRC SIGNAL rx.__REXXUtilEnd end /* if rc = 0 then */ if rc <> 43 then do /* rc <> 0 and rc <> 43 -> an error occured */ /* (error number 43 means "function not found" */ /* and is handled in the code below) */ rc = "SYNTAX ERROR " || rc SIGNAL rx.__REXXUtilEnd end /* if rc <> 43 then */ /* ------- The next statement is for debugging purpose only --------- */ say " REXXUTIL: Reloading the function <" || , rx.__funcName || "> ..." || "07"x /* ----------------------------------------------------------------- */ /* rc = 43 -> either the function is not yet */ /* loaded or dropped by another process */ /* -> reload the function */ call rxFuncAdd rx.__funcName, "REXXUTIL", rx.__funcName /* install another local error handler to avoid */ /* endless loops */ SIGNAL ON SYNTAX Name rx.__REXXUtilError rc = 0 /* and try it again */ interpret rx.__iLine rx.__REXXUTILError: /* check the result */ if rc = 0 then rc = rx.__fRC /* execution okay */ else rc = "SYNTAX ERROR " || rc /* error */ rx.__REXXUtilEnd: /* drop local variables */ drop rx. RETURN rc