Call object handle

A handle to a call object allows you to do the following dynamically:

Syntax

call-object-handle [ :attribute  | :method ]
call-object-handle
The handle to a call object.
attribute
An attribute of the call object.
method
A method of the call object. The methods let you set parameters, reset attributes to their default values, and invoke the call object.

Attributes

Methods

Examples

The following fragment dynamically invokes an external procedure non-persistently:

DEFINE VARIABLE hCall AS HANDLE NO-UNDO.

CREATE CALL hCall.

/* Invoke hello.p non-persistently */
hCall:CALL-NAME      = "hello.p".
/* Sets CALL-TYPE to the default */
hCall:CALL-TYPE  = PROCEDURE-CALL-TYPE
hCall:NUM-PARAMETERS = 1.
hCall:SET-PARAMETER(1, "CHARACTER", "INPUT", "HELLO WORLD").
hCall:INVOKE.

/* Clean up */
DELETE OBJECT hCall.

The following fragment dynamically invokes an external procedure persistently, then dynamically invokes one of its internal procedures:

DEFINE VARIABLE hCall AS HANDLE NO-UNDO.

CREATE CALL hCall.

/* Invoke persis.p persistently */
hCall:CALL-NAME  = "persis.p".
hCall:CALL-TYPE  = PROCEDURE-CALL-TYPE
hCall:PERSISTENT = TRUE.

/* IN-HANDLE automatically set to the handle of the persistent procedure */
hCall:INVOKE.

/* Invoke internal-persis-proc in persis.p */
hCall:CALL-NAME      = "internal-persis-proc".
hCall:NUM-PARAMETERS = 1.
hCall:SET-PARAMETER(1, "INTEGER", "INPUT", 333).
hCall:INVOKE.

/* Clean up */
DELETE PROCEDURE hCall:IN-HANDLE.
DELETE OBJECT hCall.

As an alternative to setting the PERSISTENT attribute, a procedure can be run persistently by setting the PROCEDURE-TYPE to "PERSISTENT". Regardless of which attribute is used, the other will automatically be set.

The following fragment dynamically invokes an external procedure as single-run, then dynamically invokes one of its internal procedures:

DEFINE VARIABLE hCall AS HANDLE NO-UNDO.

CREATE CALL hCall.

/* Invoke single.p as a single-run procedure*/
hCall:CALL-NAME  = "single.p".
hCall:CALL-TYPE  = PROCEDURE-CALL-TYPE
hCall:PROCEDURE-TYPE = SINGLE-RUN.

/* IN-HANDLE automatically set to the handle of the single-run procedure */
hCall:INVOKE.

/* Invoke internal-single-proc in single.p */
hCall:CALL-NAME      = "internal-single-proc".
hCall:NUM-PARAMETERS = 1.
hCall:SET-PARAMETER(1, "INTEGER", "INPUT", 333).
hCall:INVOKE.

/* Clean up */
DELETE PROCEDURE hCall:IN-HANDLE.
DELETE OBJECT hCall.

The previous fragment could also be used to dynamically invoke an external procedure as singleton by changing PROCEDURE-TYPE to "SINGLETON".

The following fragment uses a single call object handle multiple times:

DEFINE VARIABLE hCall AS HANDLE NO-UNDO.

CREATE CALL hCall.

/* Invoke hello.p non-persistently */
ASSIGN
  hCall:CALL-NAME      = "hello.p"
  hCall:CALL-TYPE  = PROCEDURE-CALL-TYPE
  hCall:NUM-PARAMETERS = 1.

hCall:SET-PARAMETER(1, "CHARACTER", "INPUT", "HELLO WORLD").
hCall:INVOKE.

/* Reset the call object handle */
hCall:CLEAR.

/* Invoke persis.p persistently */
ASSIGN
  hCall:CALL-NAME  = "persis.p"
  hCall:CALL-TYPE  = PROCEDURE-CALL-TYPE
  hCall:PERSISTENT = TRUE.

/* IN-HANDLE automatically set to the handle of the persistent procedure */
hCall:INVOKE.

/* Invoke internal-persis-proc in persis.p */
ASSIGN
  hCall:CALL-NAME      = "internal-persis-proc"
  hCall:CALL-TYPE  = PROCEDURE-CALL-TYPE
  hCall:NUM-PARAMETERS = 1.

hCall:SET-PARAMETER( 1, "INTEGER", "INPUT", 333).
hCall:INVOKE.

/* Clean up */
DELETE PROCEDURE hCall:IN-HANDLE.
DELETE OBJECT hCall.

The following fragment gets an attribute:

/* Get title of frame */
ASSIGN
  hCall:IN-HANDLE = myframe_handle
  hCall:CALL-TYPE = GET-ATTR-CALL-TYPE
  hCall:CALL-NAME = "TITLE".

hCall:INVOKE.

Mytitle = hCall:RETURN-VALUE.

The following fragment sets an attribute:

/* Set SESSION:NUMERIC-FORMAT to "european" */
ASSIGN
  hCall:IN-HANDLE      = "session"
  hCall:CALL-TYPE      = SET-ATTR-CALL-TYPE
  hCall:CALL-NAME      = "numeric-format"
  hCall:NUM-PARAMETERS = 1.

hCall:SET-PARAMETER( 1, "CHAR", "INPUT", "european").
hCall:INVOKE.

The following fragment drives the call object's INVOKE( ) method from a TEMP-TABLE:

/* Suppose hRuntt is a temp-table that has one record with the following    fields:
   parm_1
   parm_2
   ...
   parm_n
   run-name
   nparms
   datatypes, extent nparms
   iomodes, extent nparms */
DEFINE INPUT PARAMETER TABLE-HANDLE hRuntt.

DEFINE VARIABLE hDtypes  AS HANDLE  NO-UNDO.
DEFINE VARIABLE hIOmodes AS HANDLE  NO-UNDO.
DEFINE VARIABLE hCall    AS HANDLE  NO-UNDO.
DEFINE VARIABLE ix       AS INTEGER NO-UNDO.

ASSIGN
  hDtypes  = hRuntt:BUFFER-FIELD("datatypes")
  hIOmodes = hRuntt:BUFFER-FIELD("iOmodes").

hRuntt:FIND-FIRST.

CREATE CALL hCall.
ASSIGN
  hCall:CALL-NAME      = hRuntt:BUFFER-FIELD("run-name"):BUFFER-VALUE
  hCall:NUM-PARAMETERS = hRuntt:BUFFER-FIELD("nparms"):BUFFER-VALUE.

DO ix = 1 to hCall:NUM-PARAMETERS:
  hCall:SET-PARAMETER(ix, hDtypes:BUFFER-VALUE(ix),
    hIOmodes:BUFFER-VALUE(ix), hRuntt:BUFFER-FIELD(ix):BUFFER-VALUE).
END.

hCall:INVOKE.
DELETE OBJECT hCall.
/* If there are output parms, get values from hRuntt:BUFFER-FIELD(ix) */

The following fragment implements an ABL function, sleep, which causes the AVM to sleep for a specified number of milliseconds:

FUNCTION sleep RETURNS INTEGER (INPUT msecs AS INTEGER):
  DEFINE VARIABLE cFunction AS CHARACTER NO-UNDO INITIAL "sleep".
  DEFINE VARIABLE cLibrary  AS CHARACTER NO-UNDO INITIAL "libc.so.1".
  DEFINE VARIABLE hCall     AS HANDLE    NO-UNDO.

  CREATE CALL hCall.
  ASSIGN
    cLibrary             = "kernel32.dll" WHEN OPSYS = "WIN32"
    cFunction            = "Sleep" WHEN OPSYS = "WIN32"
    hCall:CALL-NAME      = cFunction
    hCall:LIBRARY        = cLibrary
    hCall:CALL-TYPE      = DLL-CALL-TYPE
    hCall:NUM-PARAMETERS = 1.

  hCall:SET-PARAMETER(1, "LONG", "INPUT", msecs).
  hCall:INVOKE( ).
  
  DELETE OBJECT hCall.
  RETURN msecs.
END FUNCTION.

Note that the code checks to determine on which OS it is running, and invokes the appropriate Windows DLL or UNIX shared library.

Notes

See also

RUN statement