The operator is an extension of the IEC 61131-3 standard.
The __NEW
operator reserves dynamic memory to instantiate function blocks, user-defined data
types, or arrays of standard types. The operator returns a matching typed pointer.
Requirement: In the properties dialog of the parent application, on the “Application Build Options” tab, the “Use dynamic memory allocation” option is selected.
Syntax
<pointer name> := __NEW( <type> ( , <size> )? ); __DELETE( <pointer name> ); <type> : <function block> | <data unit type> | <standard data type>
The operator generates an instance of the type <type>
and returns a pointer to this instance. Then the initialization of the instance is
called. If <type>
is a scalar standard data type, then the optional operand <size>
is also evaluated. Then the operator generates an array of type <standard data type>
and size <size>
. If the attempt to allocate memory fails, then __NEW
returns the value 0
.
Use the operator within the assignment ":=
". Otherwise an error message is displayed.
A function block or a user-defined data type whose instance is created dynamically
with __NEW
uses a fixed memory area. Here it is required that you mark the objects with the
pragma {attribute 'enable_dynamic_creation'}
. It is not required for function blocks that are part of a library.
If you change the data layout of the function block in online mode, then you cannot execute a login with an online change afterwards. This is because the memory area of the function block instance has been invalidated. You change the data layout when you add new variables to the function block, delete existing variables, or change the data types of variables.
Example
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
Function block:
{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
User-defined data type (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




NOTICE

We do not recommend the simultaneous execution of two tasks that both call the __NEW
operator. You use either a semaphore (SysSemEnter
) or a comparable technique to prevent a concurrent call of __NEW
. However, this results in a higher jitter when __NEW
is applied extensively.
We recommend that you call __NEW
operators in one task only.