Open Object Rexx™: Programming Guide | ||
---|---|---|
Prev | Chapter 10. Classic Rexx Application Programming Interfaces | Next |
There are two types of Rexx external functions:
Routines written in Rexx
Routines written in other platform-supported native code (compiled) languages
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.
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.
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:
is the address of an ASCII function name used to call the external function.
is the number of elements in the Argv array. Argv contains Argc RXSTRINGs.
is an array of null-terminated CONSTRXSTRINGs for the function arguments.
is the name of the currently defined external Rexx data queue.
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.
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.
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.
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 */ }
The following sections explain the functions for registering and using external functions.
RexxRegisterFunctionDll registers an external function that resides in a dynamic-link library routine.
retc = RexxRegisterFunctionDll(FuncName, ModuleName, EntryPoint);
is the address of an external function name. The function name must not exceed 1024 characters.
is the address of an ASCII library name. ModuleName is the library file containing the external function routine.
is the address of an ASCII dynamic-link procedure name. EntryPoint is the name of the exported external function routine within ModuleName.
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.
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 registers an external function that resides within the application code.
retc = RexxRegisterFunctionExe(FuncName, EntryPoint);
is the address of an external function name. The function name must not exceed 1024 characters.
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.
RexxDeregisterFunction deregisters an external function.
retc = RexxDeregisterFunction(FuncName);
is the address of an external function name to be deregistered.
RexxQueryFunction queries the existence of a registered external function.
retc = RexxQueryFunction(FuncName);
is the address of an external function name to be queried.
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.