Previous Next

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.
 
FOR 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 
*
*
To invoke an internal or external procedure whose calling sequence (number of parameters and the data type of each) is unknown at compile time.
Note:
If only the name of the procedure is unknown at compile time, use the RUN statement with the VALUE option—and avoid the call object altogether.
*
Note:
If only the name of the function is unknown at compile time, use the DYNAMIC-FUNCTION() function—and avoid the call object altogether.
*
*
*
*
*
If you already know the name of the attribute or procedure, you know its syntax, since the name implies certain syntax. And if you know the syntax, you know the calling sequence, since the syntax defines the calling sequence. And if you know the calling sequence, you can use widget:attribute or widget:method syntax—and avoid the call object altogether.
*
 
Syntax 
CREATE object-handle [ IN widget-pool ]
For example:
 
CREATE CALL hCall.
Note:
*
 
Syntax 
DELETE OBJECT handle.
For example:
 
DELETE OBJECT hCall.
Since the call object, by default, goes into the SESSION widget pool, not into the closest unnamed widget pool, to delete a call object created when the IN widget-pool option is not used, use the DELETE OBJECT handle syntax explicitly.
*
Setting the PROCEDURE-TYPE attribute to "PERSISTENT" will automatically set the PERSISTENT attribute to TRUE. Likewise, setting the PERSISTENT attribute to TRUE will automatically set PROCEDURE-TYPE to "PERSISTENT". Setting the PROCEDURE-TYPE and PERSISTENT attributes to conflicting values, e.g., PERSISTENT as TRUE and PROCEDURE-TYPE as "SINGLE-RUN", will result in a run-time error.
See also 
RUN statement

Previous Next
© 2013 Progress Software Corporation and/or its subsidiaries or affiliates.