Der Operator ist eine Erweiterung der Norm IEC 61131-3.
Der __NEW
-Operator reserviert dynamisch Speicher um Funktionsbausteine, benutzerdefinierte
Datentypen oder Arrays von Standarddatentypen zu instanzieren. Der Operator gibt einen
passend getypten Pointer zurück.
Voraussetzung: Im Eigenschaftendialog der übergeordneten Applikation, in der Registerkarte „Optionen Applikationserzeugung“, ist die Option „Dynamische Speicherallozierung verwenden“ aktiviert.
Syntax
<pointer name> := __NEW( <type> ( , <size> )? ); __DELETE( <pointer name> ); <type> : <function block> | <data unit type> | <standard data type>
Der Operator erzeugt eine Instanz des Typs <type>
und gibt einen Pointer auf diese Instanz zurück. Anschließend wird die Initialisierung
der Instanz aufgerufen. Wenn es sich bei <type>
um einen skalaren Standarddatentyp handelt, wird zusätzlich der optionale Operand
<size>
ausgewertet. Der Operator erzeugt dann ein Array des Typs <standard data type>
der Größe <size>
. Wenn der Versuch Speicher zu allozieren scheitert, gibt __NEW
den Wert 0
zurück.
Verwenden Sie den Operator innerhalb der Zuweisung ":=
", ansonsten wird eine Fehlermeldung ausgegeben.
Ein Funktionsbaustein oder ein benutzerdefinierter Datentyp, dessen Instanz mit __NEW
dynamisch erzeugt wird, belegt einen fixen Speicherbereich. Dafür ist es erforderlich,
dass Sie die Objekte mit dem Pragma {attribute 'enable_dynamic_creation'}
kennzeichnen. Das ist bei Funktionsbausteinen, die Teil einer Bibliothek sind, nicht
erforderlich.
Wenn Sie im Onlinebetrieb das Datenlayout des Funktionsbausteins ändern, können Sie anschließend kein Einloggen mit Online-Change ausführen. Der Speicherbereich der Funktionsbaustein-Instanz ist nämlich ungültig geworden. Eine Änderung des Datenlayouts nehmen Sie vor, wenn Sie beim Funktionsbaustein neue Variablen hinzufügen, bestehende Variablen löschen oder Datentypen von Variablen ändern.
Beispiel
Array (DWORD
):
PROGRAM PLC_PRG VAR pdwScalar : POINTER TO DWORD; //Typed pointer xInit : BOOL := TRUE; xDelete : BOOL; END_VAR IF (xInit) THEN pdwScalar := __NEW(DWORD, 16); // Allocates memory (16 dwords) and assigns them to pointer pdwScalar END_IF IF (xDelete) THEN __DELETE(pdwScalar); // Frees memory of pointer END_IF
Funktionsbaustein:
{attribute 'enable_dynamic_creation'} FUNCTION_BLOCK FBComputeGamma VAR_INPUT iAlpha : INT; iBeta : INT; END_VAR VAR_OUTPUT iGamma : INT; END_VAR VAR END_VAR iGamma := iAlpha + iBeta; PROGRAM PLC_PRG VAR pComputeGamma : POINTER TO FBComputeGamma; // Typed pointer xInit : BOOL := TRUE; xDelete : BOOL; iResult : INT; END_VAR IF (xInit) THEN pComputeGamma := __NEW(FBComputeGamma); // Allocates memory xInit := FALSE; END_IF pComputeGamma^.iAlpha := (pComputeGamma^.iAlpha + 1)MOD 100; // Sets first input of pComputeGamma pComputeGamma^.iBeta := 10; // Sets second input of pComputeGamma pComputeGamma^(); // Calls the FB pComputeGamma is pointing to iResult := pComputeGamma^.iGamma; // Reads output of pComputeGamma IF (xDelete) THEN __DELETE(pComputeGamma); // Frees memory END_IF
Benutzerdefinierter Datentyp (DUT):
{attribute 'enable_dynamic_creation'} TYPE ABCDATA : STRUCT iA, iB, iC, iD : INT; END_STRUCT END_TYPE PROGRAM PLC_PRG VAR pABCData : POINTER TO ABCDATA; // Typed pointer xInit : BOOL := TRUE; xDelete : BOOL; END_VAR IF (xInit) THEN pABCData := __NEW(ABCDATA); // Allocates memory xInit := FALSE; END_IF IF (xDelete) THEN __DELETE(pABCData); // Frees memory END_IF
Array (BYTE):
PROGRAM PLC_PRG VAR pbDataAlpha : POINTER TO BYTE; pbDataBeta : POINTER TO BYTE; xInit : BOOL := TRUE; xDelete : BOOL; usiCnt : USINT; bTestC: BYTE; END_VAR IF (xInit) THEN pbDataAlpha := __NEW(BYTE, 16); // Allocates 16 bytes for pbDataAlpha pbDataBeta := __NEW(BYTE); // Allocates memory for pbDataBeta xInit := FALSE; FOR usiCnt := 0 TO 15 DO pbDataAlpha[usiCnt] := usiCnt; // Writes to new array END_FOR pbDataBeta^:= 16#FF; // Writes to new data END_IF bTestC := pbDataAlpha[12]; // Reads new array by index access IF (xDelete) THEN // Frees memory __DELETE(pbDataAlpha); __DELETE(pbDataBeta); END_IF




HINWEIS

Es ist nicht ratsam, zwei Tasks gleichzeitig auszuführen, die beide den __NEW
-Operator aufrufen. Entweder Sie verwenden ein Semaphor (SysSemEnter
) oder eine vergleichbare Technik, um einen konkurrierenden Aufruf von __NEW
zu verhindern. Das bewirkt allerdings, dass bei umfangreicher Nutzung von __NEW
ein höherer Jitter entsteht.
Empfehlenswert ist, nur in einer Task __NEW
-Operatoren aufzurufen.