PLC

ANY and ANY_<type>

When implementing a function or a method, you can declare inputs (VAR_INPUT) as variables with a generic IEC data 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.

An input of the data type ANY or ANY_<type> cannot be assigned a constant when calling the function or method.

The generic IEC data types shown below are supported. The table shows which generic data type allows 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
ANY_NUM
ANY_REAL
REAL, LREAL
ANY_INT
USINT, UINT, UDINT, ULINT
SINT, INT, DINT, LINT
ANY_STRING
 
STRING, WSTRING
 

Predefined structure

When the code is compiled, an ANY data type is replaced internally with the following structure:

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

The actual call parameter is then assigned to the structure elements at runtime.

 
 

Sample 1: Transfer of elementary data types to inputs with a 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 2: 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 3: Determination of the data type transferred

The function checks whether the variable transferred 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