ANY und ANY_<Typ>

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_<Typ>. 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>.

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
    // Type of the current parameter
    typeclass  : __SYSTEM.TYPE_CLASS ;
    // Pointer to the current parameter
    pvalue     : POINTER TO BYTE;
    // Size of the data to which the pointer points
    diSize     : DINT;
END_STRUCT
END_TYPE
ANY und ANY_<Typ> 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

<Gültigkeitsbereich> <POU-Name> : <Datentyp des Rückgabewerts>
VAR_INPUT
    <Variablenname> : <Generischer Datentyp>;
END_VAR

<Gültigkeitsbereich>

Possible scopes:

  • FUNCTION
  • FUNCTION_BLOCK
  • METHOD

<POU-Name>

POU name

: <Datentyp des Rückgabewerts>

Optional

<Variablenname>

Name of the input variable

<Generischer Datentyp>

ANY, ANY_BIT, ANY_DATE, ANY_NUM, ANY_REAL, ANY_INT or ANY_STRING

The table shows the hierarchy of generic data types and provides information on which generic data type of the formal parameter (declaration) allows which elementary data types of the argument (call).

Generic data types

Elementary data types

ANY

ANY_BIT

 

  • BYTE
  • WORD
  • DWORD
  • LWORD

ANY_DATE

 

  • DATE
  • DATE_AND_TIME, DT
  • 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

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

<Name der Funktion> (<Argument>)

Function block call syntax

<Name der Funktionsbausteininstanz> ( <Name der Eingangsvariablen> := <Argument> );

Method call syntax


<Name der Fuktionsbausteinstanz> . <Name der Methode> ( <Name der Eingangsvariablen> := <Argument> );

<Argument>

Transfer variable

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