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 |
|
|
ANY_DATE |
|
| |
ANY_NUM | ANY_REAL |
| |
ANY_INT |
| ||
ANY_STRING |
|
|
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
Ü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