External Function Interface

There are two types of Rexx external functions:

External functions written in Rexx do not need to be registered. These functions are found by a disk search for a Rexx procedure file that matches the function name.

There are two styles of native code routines supported by Open Object Rexx. Registered External Functions are an older style of routine that is only capable of dealing with String data. These routines do not have access to any of the object-oriented features of the language. The registered external functions are described here, but should be considered only if compability with older versions of Object Rexx or other Rexx interpreters is a consideration.

The newer style functions have access to Rexx objects and a fuller set of APIs for interfacing with the interpreter runtime. These functions are the preferred method for writing Open Object Rexx extensions are are defined in Building an External Native Library.

Registering External Functions

An external function can reside in the same module (executable or library) as an application, or in a separate lodable library library. RexxRegisterFunctionExe registers external functions within an application module. External functions registered with RexxRegisterFunctionExe are available only to Rexx programs called from the registering application.

The RexxRegisterFunctionDll interface registers external functions that reside in a dynamic-link library. Any Rexx program can access such an external function after it is registered. It can also be registered directly from a Rexx program using the Rexx RXFUNCADD built-in function.

Creating External Functions

The following is a sample external function definition:

size_t REXXENTRY SysLoadFuncs(
     const char *Name,                   /* name of the function       */
     size_t      Argc,                   /* number of arguments        */
     CONSTRXSTRING  Argv[],              /* list of argument strings   */
     const char *Queuename,              /* current queue name         */
     PRXSTRING   Retstr)                 /* returned result string     */

where:

Name

is the address of an ASCII function name used to call the external function.

Argc

is the number of elements in the Argv array. Argv contains Argc RXSTRINGs.

Argv

is an array of null-terminated CONSTRXSTRINGs for the function arguments.

Queuename

is the name of the currently defined external Rexx data queue.

Retstr

is the address of an RXSTRING for the returned value. Retstr is a character string function or subroutine return value. When a Rexx program calls an external function with the Rexx CALL instruction, Retstr is assigned to the special Rexx variable RESULT. When the Rexx program calls an external function with a function call, Retstr is used directly within the Rexx expression.

The Rexx interpreter provides a default 256-byte RXSTRING in Retstr. A longer RXSTRING can be allocated with RexxAllocateMemory(size) if the returned string is longer than 256 bytes. The Rexx interpreter releases Retstr with RexxFreeMemory(ptr) when the external function completes.

Returns

is an integer return code from the function. When the external function returns 0, the function completed successfully. Retstr contains the return value. When the external function returns a nonzero return code, the Rexx interpreter raises Rexx error 40, "Incorrect call to routine". The Retstr value is ignored.

If the external function does not have a return value, the function must set Retstr to an empty RXSTRING (null strptr). When an external function called as a function does not return a value, the interpreter raises error 44, "Function or message did not return data". When an external function called with the Rexx CALL instruction does not return a value, the Rexx interpreter drops (unassigns) the special variable RESULT.

Calling External Functions

RexxRegisterFunctionExe external functions are local to the registering process. Another process can call the RexxRegisterFunctionExe to make these functions local to this process. RexxRegisterFunctionDll functions, however, are available to all processes. The function names cannot be duplicated.

Example

size_t REXXENTRY SysMkDir(
     const char *Name,                 /* name of the function       */
     size_t      Argc,                 /* number of arguments        */
     CONSTRXSTRING  Argv[],            /* list of argument strings   */
     const char *Queuename,            /* current queue name         */
     PRXSTRING   Retstr)               /* returned result string     */
{
  ULONG  rc;                           /* Return code of function    */

  if (Argc != 1)                       /* must be 1 argument         */
    return 40;                         /* incorrect call if not      */

                                       /* make the directory         */
  rc = !CreateDirectory(Argv[0].strptr, NULL);

  sprintf(Retstr->strptr, "%d", rc);   /* result: <> 0 failed        */
                                       /* set proper string length   */
  Retstr->strlength = strlen(Retstr->strptr);
  return 0;                            /* successful completion      */
}

External Function Interface Functions

The following sections explain the functions for registering and using external functions.

RexxRegisterFunctionDll

RexxRegisterFunctionDll registers an external function that resides in a dynamic-link library routine.

retc = RexxRegisterFunctionDll(FuncName, ModuleName, EntryPoint);

Parameters

FuncName (const char *) - input

is the address of an external function name. The function name must not exceed 1024 characters.

ModuleName (const char *) - input

is the address of an ASCII library name. ModuleName is the library file containing the external function routine.

EntryPoint (const char *) - input

is the address of an ASCII dynamic-link procedure name. EntryPoint is the name of the exported external function routine within ModuleName.

Return Codes

RXFUNC_OK 0The call to the function completed successfully.
RXFUNC_DEFINED10The requested function is already registered.
RXFUNC_NOMEM20There is not enough memory to register a new function.

Remarks

On Windows, External functions that reside in a dynamic-link library routine must be exported. You can do this by specifying a module-definition (.DEF) file that lists the external functions in the EXPORT section. For example:

EXPORTS
   SYSMKDIR = SysMkDir

A Rexx procedure can register dynamic-link library-external functions with the RXFUNCADD built-in function. For example:

                               /* register function SysLoadFuncs  */
                               /* in dynamic link library RexxUTIL*/
Call RxFuncAdd "SysLoadFuncs", "RexxUTIL", "SysLoadFuncs"
Call SysLoadFuncs              /* call to load other functions    */

RXFUNCADD registers the external function SysLoadFuncs as routine SysLoadFuncs in the rexxutil library. SysLoadFuncs registers additional functions in rexxutil with RexxRegisterFunctionDll. See the SysLoadFuncs routine below for a function registration example.

Example

static const char *RxFncTable[] =      /* function package list      */
{
      "SysCls",
      "SysCurpos",
      "SysCurState",
      "SysDriveInfo",
}


size_t REXXENTRY SysLoadFuncs(
     const char *Name,                   /* name of the function       */
     size_t      Argc,                   /* number of arguments        */
     CONSTRXSTRING  Argv[],              /* list of argument strings   */
     const char *Queuename,              /* current queue name         */
     PRXSTRING   Retstr)                 /* returned result string     */
{
  INT    entries;                      /* Number of entries          */
  INT    j;                            /* counter                    */

  Retstr->strlength = 0;               /* set null string return     */

  if (Argc > 0)                        /* check arguments            */
    return 40;                         /* too many, raise an error   */

                                       /* get count of arguments     */
  entries = sizeof(RxFncTable)/sizeof(const char *);
                                       /* register each function in  */
  for (j = 0; j < entries; j++) {      /* the table                  */
    RexxRegisterFunctionDll(RxFncTable[j],
          "RexxUTIL", RxFncTable[j]);
  }
  return 0;                            /* successful completion      */
}

RexxRegisterFunctionExe

RexxRegisterFunctionExe registers an external function that resides within the application code.

retc = RexxRegisterFunctionExe(FuncName, EntryPoint);

Parameters

FuncName (const char *) - input

is the address of an external function name. The function name must not exceed 1024 characters.

EntryPoint (REXXPFN) - input

is the address of the external function entry point within the executable application file. Functions registered with RexxRegisterFunctionExe are local to the current process. Rexx procedures in the same process as the RexxRegisterFunctionExe issuer can call local external functions.

Return Codes

RXFUNC_OK 0The call to the function completed successfully.
RXFUNC_DEFINED10The requested function is already registered.
RXFUNC_NOMEM20There is not enough memory to register a new function.

RexxDeregisterFunction

RexxDeregisterFunction deregisters an external function.

retc = RexxDeregisterFunction(FuncName);

Parameters

FuncName (const char *) - input

is the address of an external function name to be deregistered.

Return Codes

RXFUNC_DEFINED10The requested function is already registered.
RXFUNC_NOTREG30The requested function is not registered.

RexxQueryFunction

RexxQueryFunction queries the existence of a registered external function.

retc = RexxQueryFunction(FuncName);

Parameters

FuncName (const char *) - input

is the address of an external function name to be queried.

Return Codes

RXFUNC_OK 0The call to the function completed successfully.
RXFUNC_NOTREG30The requested function is not registered.

Remarks

RexxQueryFunction returns RXFUNC_OK only if the requested function is available to the current process. If not, the RexxQueryFunction searches the external RexxRegisterFunctionDll function list.