Die Datentypen ANY
oder ANY_<type>
werden in Schnittstellen von Funktionen, Funktionsbausteinen oder Methoden verwendet,
um Eingangsparameter, deren Typ unbekannt oder beliebig ist, formal zu typisieren:
Die Eingangsvariablen (VAR_INPUT
) haben einen generischen Datentyp.
Der Compiler ersetzt den Typ der Eingangsvariable intern mit der unten beschriebenen Datenstruktur, wobei der Wert wird nicht direkt übergeben wird. Stattdessen wird ein Zeiger auf den eigentlichen Wert übergeben, weswegen nur eine Variablen ü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.
Literale, ersetzte Konstanten und Ergebnisse von Funktionsaufrufen oder Ausdrücken
können nicht an Eingangsvariablen (VAR_IN_OUT
) übergeben werden.
Interne Datenstruktur bei 'ANY' und 'ANY_<type>'
Beim Übersetzen des Codes werden die Eingangsvariablen mit ANY
-Datentyp intern durch die folgende Struktur typisiert. Bei Aufruf des Programmierbausteins (zur
Laufzeit) wird das Argument an einen Referenzparameter übergeben.
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.
Beispiel
Die Funktion vergleicht, ob zwei Eingangsvariablen den gleichen Typ und den gleichen Wert haben.
FUNCTION funGenericCompare : BOOL VAR_INPUT any1 : ANY; any2 : ANY; END_VAR VAR pTest : POINTER TO ARRAY [0..100] OF POINTER TO DWORD; diCount: DINT; END_VAR pTest := ADR(any1); Generic_Compare := FALSE; IF any1.typeclass <> any2.typeclass THEN RETURN; END_IF IF any1.diSize <> any2.diSize THEN RETURN; END_IF // Byte comparison FOR iCount := 0 TO any1.diSize-1 DO IF any1.pvalue[iCount] <> any2.pvalue[iCount] THEN RETURN; END_IF END_FOR Generic_Compare := TRUE; RETURN; // END_FUNCTION
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
Beispiel
FUNCTION funComputeAny : BOOL VAR_INPUT anyInput1 : ANY; // valid data type see table END_VAR // END_FUNCTION FUNCTION_BLOCK FB_ComputeAny VAR_INPUT anyInput1 : ANY; END_VAR // END_FUNCTION_BLOCK FUNCTION_BLOCK FB_ComputeMethod METHOD methComputeAnny : BOOL VAR_INPUT anyInput1 : ANY_INT; // valid data types are SINT, INT, DINT, LINT, USINT, UINT, UDINT, ULINT END_VAR //END_METHOD
Ab Compilerversion >= 3.5.1.0 werden die in der Tabelle dargestellten generischen IEC-Datentypen unterstützt.
Die Tabelle stellt die Hierarchie der generischen Datentypen dar und gibt Auskunft, welcher generische Datentyp des formalen Parameters (Deklaration) welche elementaren Datentypen des Arguments (Aufruf) erlaubt.
Generischer Datentyp beim formalen Parameter |
Erlaubter elementarer Datentyp beim tatsächlichen Parametrer (Argument) |
||
---|---|---|---|
|
|
|
|
|
|
||
|
|
|
|
|
|
||
|
|
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
PROGRAM PLC_PRG VAR byValue : BYTE := 16#AB; iValue : INT := -1234; xResultByte : BOOL; xResultInt : BOOL; fbComputeAnyByte : FB_ComputeAny; fbComputeAnyInt : FB_ComputeAny; fbComputeM1 : FB_ComputeMethod; fbComputeM2 : FB_ComputeMethod; byN : BYTE := 1; wBitField1 : WORD := 16#FFFF; wBitField2 : WORD := 16#0001; xInit : BOOL; xResult : BOOL; END_VAR xResultByte := funComputeAny(byValue); xResultInt := funComputeAny(iValue); xResult := funGenericCompare(wBitField1, wBitField2); fbComputeAnyByte(anyInput1 := byValue); fbComputeAnyInt(anyInput1 := iValue); fbComputeM1.methComputeAnny(anyInput1 := byValue); fbComputeM2.methComputeAnny(anyInput1 := iValue); // END_PRG