ANY und ANY_<Typ>

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

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

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

Ü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 (einer Eingangsvariablen).

Syntax

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

<Gültigkeitsbereich>

Mögliche Gültigkeitsbereiche:

  • FUNCTION
  • FUNCTION_BLOCK
  • METHOD

<POU-Name>

Name des POU

: <Datentyp des Rückgabewerts>

Optional

<Variablenname>

Name der Eingangsvariable

<Generischer Datentyp>

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

Die Tabelle stellt die Hierarchie der generischen Datentypen dar und gibt Auskunft darüber, welcher generische Datentyp des formalen Parameters (Deklaration) welche elementaren Datentypen des Arguments (Aufruf) erlaubt.

Generische Datentypen

Elementare Datentypen

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

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

<Name der Funktion> (<Argument>)

Syntax Funktionsbausteinaufruf

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

Syntax Methodenaufruf


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

<Argument>

Übergabevariable

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