The function RxFuncDrop()

[Autolink] Menu

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


[Back: RxFuncAdd]
[Next: The function RxMessageBox()]