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.