ANY und ANY_<type>

Bei der Implementierung einer Funktion, einer Methode oder (ab Build 4026) eines Funktionsbausteins können Sie Eingänge (VAR_INPUT) als Variablen mit generischem IEC-Datentyp, ANY oder ANY_<type>, deklarieren. Folglich können Sie Aufrufe implementieren, deren Aufrufparameter sich im Datentyp unterscheiden.

Zur Laufzeit können Sie innerhalb des Programmierbausteins für die Eingangsvariable den übergebenen Wert und dessen Typ über eine vordefinierte Struktur abfragen.

Der Compiler ersetzt den Typ der Eingangsvariable intern mit der unten beschriebenen Datenstruktur, wobei der Wert nicht direkt übergeben wird. Stattdessen wird ein Zeiger auf den eigentlichen Wert übergeben, weswegen nur eine Variable übergeben werden kann. Erst beim Aufruf wird also der Datentyp konkretisiert. Aufrufe solcher Programmierbausteine können daher mit Argumenten, die jeweils unterschiedliche Datentypen haben, erfolgen.

Einem Eingang vom Datentyp ANY oder ANY_<type> kann bei dem Aufruf der Funktion, des Funktionsbausteins oder der Methode keine Konstante und keine Eigenschaft zugewiesen werden. Andersherum kann einer Eigenschaft keine Variable vom Datentyp ANY oder ANY_<type> zugewiesen werden.

Die unten dargestellten generischen IEC-Datentypen werden unterstützt. Die Tabelle stellt dar, welche generischen Datentypen welche elementaren Datentypen erlauben.

Generische Datentypen

Elementare Datentypen

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

Interne Datenstruktur bei 'ANY' und 'ANY_<type>'

Beim Übersetzen des Codes werden die Eingangsvariablen mit ANY-Datentyp intern mit der folgenden Struktur ersetzt. Der tatsächliche Aufrufparameter wird den Strukturelementen zur Laufzeit zugewiesen.

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 und ANY_<type> 1:

Über diese Struktur können Sie innerhalb des Programmierbausteins auf die Eingangsvariable zugreifen und beispielsweise den übergebenen Wert abfragen.

Deklaration

Die Syntaxbeschreibungen beziehen sich auf einen Programmierbaustein mit genau einem Parameter (eine Eingangsvariable).

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

Aufruf

Die Syntaxbeschreibungen beziehen sich auf einen Programmierbaustein mit genau einem Parameter, dem ein Argument übergeben wird. Der Datentyp des Arguments konkretisiert dabei den generischen Datentyp der Eingangsvariable. Beispielsweise können Argumente des Typs BYTE, WORD, DWORD, LWORD an eine ANY_BIT-Eingangsvariable übergeben werden.

Syntax Funktionsaufruf

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

Syntax Funktionsbausteinaufruf

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

Syntax Methodenaufruf

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

Beispiel 1: Übergabe von elementaren Datentypen an Eingänge mit generischem Datentyp

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);

Beispiel 2: Übergabe von elementaren Datentypen an Eingänge mit generischem Datentyp

Die Übergabeparameter der Funktionsaufrufe haben unterschiedliche Datentypen.

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);

Beispiel 3: Vergleich zweier übergebener Variablen

Die Funktion vergleicht, ob die zwei übergebenen Variablen den gleichen Typ und den gleichen Wert haben.

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;

Beispiel 4: Feststellung des übergebenen Datentyps

Die Funktion überprüft, ob die übergebene Variable vom Typ REAL oder LREAL ist. Wenn dies der Fall ist, wird der Wert der Variablen gerundet.

// 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