ANY and ANY_<type>

When implementing a function, a method or a function block (from build 4026), you can declare inputs (VAR_INPUT) as variables with generic IEC date type ANY or ANY_<type>. Consequently you can implement calls whose call parameters differ by their data type.

At runtime you can query the value transferred and its data type via a predefined structure within the programming block for the input variable.

The compiler internally replaces the type of the input variable with the data structure described below, but the value is not directly transferred. Instead, a pointer to the actual value is transferred, for which reason only one variable can be transferred. Therefore, the data type is only concretized at the call. Calls of such programming blocks can therefore take place with arguments that each have different data types.

An input of the data type ANY or ANY_<type> can neither be assigned any constants nor any property when calling the function, the function block or the method. Conversely, a property cannot be assigned any variable of the data type ANY or ANY_<type>.

The generic IEC data types shown below are supported. The table shows which generic data types allow which elementary data types.

Generic data types

Elementary data types

ANY

ANY_BIT

 

  • BYTE
  • WORD
  • DWORD
  • LWORD

ANY_DATE

 

  • DATE_AND_TIME, DT
  • DATE
  • TIME_OF_DAY, TOD
  • LDATE
  • LDATE_AND_TIME, LDT
  • LTIME_OF_DAY, LTOD

ANY_NUM

ANY_REAL

  • REAL
  • LREAL

ANY_INT

  • USINT
  • UINT
  • UDINT
  • ULINT
  • SINT
  • INT
  • DINT
  • LINT

ANY_STRING

 

  • STRING
  • WSTRING

Internal data structure with 'ANY' and 'ANY_<type>'

When compiling the code, the input variables with ANY data type are replaced internally with the following structure. The structure elements are assigned to the actual call parameter at runtime.

TYPE AnyType :
STRUCT
      // the type of the actual parameter
  typeclass  : __SYSTEM.TYPE_CLASS ;
      // the pointer to the actual parameter
  pvalue     : POINTER TO BYTE;
      // the size of the data, to which the pointer points
  diSize     : DINT;
END_STRUCT
END_TYPE
ANY and ANY_<type> 1:

Via this structure you can access the input variable inside the programming block and, for example, query the transferred value.

Declaration

The syntax descriptions refer to a programming block with precisely one parameter (one input parameter).

Syntax

FUNCTION | FUNCTION_BLOCK | METHOD <POU name>
( : <return data type> )?
VAR_INPUT
    <input variable name> : <generic data type>;
END_VAR
<generic data type> = ANY | ANY_BIT | ANY_DATE |
ANY_NUM | ANY_REAL | ANY_INT | ANY_STRING

Call

The syntax descriptions refer to a programming block with precisely one parameter, to which an argument is transferred. The data type of the argument concretizes the generic data type of the input variable. For example, arguments of the type BYTE, WORD, DWORD, LWORD can be transferred to a ANY_BIT input variable.

Function call syntax

<variable name> := <function name> ( <argument name> );
<argument name> : variable with valid data type

Function block call syntax

<function block name> ( <input variable name> := <argument name> );

Method call syntax

<function block name> . <method name> ( <input variable name> := <argument name> );

Sample 1: transfer of elementary data types to inputs with generic data type

FUNCTION F_ComputeAny : BOOL 
VAR_INPUT
    anyInput1         : ANY; // valid data type see table
END_VAR
FUNCTION_BLOCK FB_ComputeAny 
VAR_INPUT
    anyInput1     : ANY;
END_VAR
FUNCTION_BLOCK FB_ComputeMethod 
METHOD ComputeAny : BOOL
VAR_INPUT
    anyInput1     : ANY_INT; // valid data types are SINT, INT, DINT,INT, USINT, UINT, UDINT, ULINT
END_VAR
PROGRAM PLC_PRG 
VAR
    fbComputeAnyByte  : FB_ComputeAny;
    fbComputeAnyInt   : FB_ComputeAny;

    fbComputeM1       : FB_ComputeMethod;
    fbComputeM2       : FB_ComputeMethod;

    nByte             : BYTE := 16#AB;
    nInt              : INT  := -1234;
    bResultByte       : BOOL;
    bResultInt        : BOOL;
END_VAR
bResultByte := F_ComputeAny(nByte); 
bResultInt  := F_ComputeAny(nInt);

fbComputeAnyByte(anyInput1 := nByte);
fbComputeAnyInt(anyInput1 := nInt);

fbComputeM1.methComputeAny(anyInput1 := nByte);
fbComputeM2.methComputeAny(anyInput1 := nInt);

Sample 2: transfer of elementary data types to inputs with generic data type

The transfer parameters of the function calls have different data types.

FUNCTION F_AnyBitFunc    : BOOL
VAR_INPUT
    value : ANY_BIT;
END_VAR

FUNCTION F_AnyDateFunc   : BOOL
VAR_INPUT
    value : ANY_DATE;
END_VAR

FUNCTION F_AnyFunc       : BOOL
VAR_INPUT
    value : ANY;
END_VAR

FUNCTION F_AnyIntFunc    : BOOL
VAR_INPUT
    value : ANY_INT;
END_VAR

FUNCTION F_AnyNumFunc    : BOOL
VAR_INPUT
    value : ANY_NUM;
END_VAR

FUNCTION F_AnyRealFunc   : BOOL
VAR_INPUT
    value : ANY_REAL;
END_VAR

FUNCTION F_AnyStringFunc : BOOL
VAR_INPUT
    value : ANY_STRING;
END_VAR
PROGRAM MAIN
VAR
    bBOOL            : BOOL           := TRUE;
    nBYTE            : BYTE           := 16#AB;
    nWORD            : WORD           := 16#1234;
    nDWORD           : DWORD          := 16#6789ABCD;
    nLWORD           : LWORD          := 16#0123456789ABCDEF;
    sSTRING          : STRING         := 'xyz';
    wsWSTRING        : WSTRING        := "abc";
    dtDATEANDTIME    : DATE_AND_TIME  := DT#2017-02-20-11:07:00;
    dDATE            : DATE           := D#2017-02-20;
    tdTIMEOFDAY      : TIME_OF_DAY    := TOD#11:07:00;
    fREAL            : REAL           := 42.24;
    fLREAL           : LREAL          := 24.42;
    nUSINT           : USINT          := 12;
    nUINT            : UINT           := 1234;
    nUDINT           : UDINT          := 12345;
    nULINT           : ULINT          := 123456;
    nSINT            : SINT           := -12;
    nINT             : INT            := -1234;
    nDINT            : DINT           := -12345;
    nLINT            : LINT           := -123456;
END_VAR
F_AnyFunc(bBOOL);
F_AnyFunc(nBYTE);
F_AnyFunc(nWORD);
F_AnyFunc(nDWORD);
F_AnyFunc(nLWORD);
F_AnyFunc(sSTRING);
F_AnyFunc(wsWSTRING);
F_AnyFunc(dtDATEANDTIME);
F_AnyFunc(tdTIMEOFDAY);
F_AnyFunc(fREAL);
F_AnyFunc(fLREAL);
F_AnyFunc(nUSINT);
F_AnyFunc(nUINT);
F_AnyFunc(nUDINT);
F_AnyFunc(nULINT);
F_AnyFunc(nSINT);
F_AnyFunc(nINT);
F_AnyFunc(nDINT);
F_AnyFunc(nLINT);

F_AnyBitFunc(nBYTE);
F_AnyBitFunc(nWORD);
F_AnyBitFunc(nDWORD);
F_AnyBitFunc(nLWORD);

F_AnyStringFunc(sSTRING);
F_AnyStringFunc(wsWSTRING);

F_AnyDateFunc(dtDATEANDTIME);
F_AnyDateFunc(dDATE);
F_AnyDateFunc(tdTIMEOFDAY);

F_AnyNumFunc(fREAL);
F_AnyNumFunc(fLREAL);
F_AnyNumFunc(nUSINT);
F_AnyNumFunc(nUINT);
F_AnyNumFunc(nUDINT);
F_AnyNumFunc(nULINT);
F_AnyNumFunc(nSINT);
F_AnyNumFunc(nINT);
F_AnyNumFunc(nDINT);
F_AnyNumFunc(nLINT);

F_AnyRealFunc(fREAL);
F_AnyRealFunc(fLREAL);

F_AnyIntFunc(nUSINT);
F_AnyIntFunc(nUINT);
F_AnyIntFunc(nUDINT);
F_AnyIntFunc(nULINT);
F_AnyIntFunc(nSINT);
F_AnyIntFunc(nINT);
F_AnyIntFunc(nDINT);
F_AnyIntFunc(nLINT);

Sample 3: comparison of two transferred variables

The function compares the two variables transferred to determine whether they are of the same type and have the same value.

FUNCTION F_GenericCompare : BOOL
VAR_INPUT
    any1 : ANY;
    any2 : ANY;
END_VAR
VAR
    nCount: DINT;
END_VAR
IF any1.typeclass <> any2.typeclass THEN
   RETURN;
END_IF

IF any1.diSize <> any2.diSize THEN
    RETURN;
END_IF

// Byte comparison
FOR nCount := 0 TO any1.diSize-1 DO
    IF any1.pvalue[nCount] <> any2.pvalue[nCount] THEN
        RETURN;
    END_IF
END_FOR

F_GenericCompare := TRUE;

Sample 4: determination of the transferred data type

The function checks whether the transferred variable is of the type REAL or LREAL. If this is the case, the value of the variable is rounded.

// function to round transfer parameters of the type REAl and LREAL (other types are detected as invalid)
FUNCTION F_RoundFloatingValue : INT
VAR_INPUT
    anyIn        : ANY;               // input variable of the type ANY
END_VAR
VAR
    pAnyReal     : POINTER TO REAL;   // pointer to a variable of the type REAL
    pAnyLReal    : POINTER TO LREAL;  // pointer to a variable of the type LREAL
END_VAR
VAR_OUTPUT
    bInvalidType : BOOL;              // output variable with value TRUE if the transferred parameter has an invalid type
END_VAR
// round floating value for a transfer parameter of the type REAL
IF (anyIn.TypeClass = __SYSTEM.TYPE_CLASS.TYPE_REAL) THEN
    pAnyReal              := anyIn.pValue;
    F_RoundFloatingValue  := REAL_TO_INT(pAnyReal^);

// round floating value for a transfer parameter of the type LREAL
ELSIF (anyIn.TypeClass = __SYSTEM.TYPE_CLASS.TYPE_LREAL) THEN
    pAnyLReal             := anyIn.pValue;
    F_RoundFloatingValue  := LREAL_TO_INT(pAnyLReal^);

// inform about invalid type if the transfer parameter is not of the type REAL or LREAL
ELSE
    bInvalidType          := TRUE;
END_IF