__NEW

The operator is an extension of the IEC 61131-3 standard.

The __NEW operator dynamically reserves memory around function blocks to instantiate user-defined data types or arrays of standard data types. The operator returns a suitable typed pointer.

Syntax:

<pointer name> := __NEW( <type> ( , <size> )? );
__DELETE( <pointer name> );
<type> : <function block> | <data unit type> | <standard data type>
// (...)? : Optional

Sample:

pScalarType := __NEW(ScalarType, length);

The __NEW operator creates 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 standard scalar data type, the optional operand <size> is also evaluated. In this case the operator generates an array of type <standard data type> and length <size> (number of elements). If the memory allocation attempt fails, __NEW returns the value 0.

Use the __NEW operator within an assignment (":="), otherwise an error message will be issued.

__NEW 1:

No type change is possible via online change

A function block or user-defined data type whose instance is created dynamically with __NEW occupies a fixed memory area. It cannot change its data layout using the online change feature. This means that no new variables can be added, no variables can be deleted, and no types can be changed. This ensures that the pointer to this object remains valid after the online change.

For this reason, the __NEW operator can only be applied to function blocks/DUTs from libraries and to function blocks/DUTs with the attribute 'enable_dynamic_creation'. If the interface of such a function block/DUT is changed, TwinCAT issues an error message.

Dynamic memory is allocated from the router memory pool.

__NEW 2:

Status information of the TwinCAT router

The function block FB_GetRouterStatusInfo from the Tc2_Utilities library can be used to read status information of the TwinCAT router, such as the available router memory, from the PLC.

A dynamic memory reserved with __NEW must be explicitly released using __DELETE. This must be done either already in the same task cycle or at the latest before the PLC is shut down. Otherwise, a so-called memory leak may occur. As a result, other program parts can no longer reserve memory, which can lead to an unstable system. It is recommended to use the PLC library Tc3_DynamicMemory to simplify the handling with dynamic memory.

Allocating a STRING variable:

If you wish to allocate a STRING of the length cLength, use BYTE instead of STRING as the data type.

VAR CONSTANT
    cLength : UINT := 150;
END_VAR
VAR
    bNew    : BOOL;
    pString : POINTER TO STRING(cLength);
    bDelete : BOOL;
END_VAR
IF bNew AND (pSTRING = 0) THEN
    pString := __NEW(BYTE, cLength);
    bNew    := FALSE;
END_IF

IF bDelete THEN
    __DELETE(pSTRING);
    bDelete := FALSE;
END_IF

Sample with structure:

Structure ST_sample:

{attribute 'enable_dynamic_creation'}
TYPE ST_Sample :
STRUCT
    a,b,c,d,e,f : INT;
END_STRUCT
END_TYPE

MAIN program:

PROGRAM MAIN
VAR
    pDut    : POINTER TO ST_Sample;
    bNew    : BOOL := TRUE;
    bDelete : BOOL;
END_VAR
IF bNew AND (pDut = 0) THEN
    pDut := __NEW(ST_Sample);
    bNew := FALSE;
END_IF

IF bDelete THEN
    __DELETE(pDut);
    bDelete := FALSE;
END_IF

Sample with function block:

Function block FB_Dynamic:

{attribute 'enable_dynamic_creation'}
FUNCTION_BLOCK FB_Dynamic
VAR
    nCounts : INT;
END_VAR

Method Increase:

METHOD Increase : INT
VAR_INPUT
    nCountStep : INT;
END_VAR
nCounts := nCounts + nCountStep;
Increase := nCounts;

MAIN program:

PROGRAM MAIN
VAR
    pFB       : POINTER TO FB_Dynamic;
    nResult   : INT;
    nIncrease : INT := 5;
    bNew      : BOOL;
    bDelete   : BOOL;
END_VAR
IF bNew AND (pFB = 0) THEN
    pFB := __NEW(FB_Dynamic);
    bNew := FALSE;
END_IF

IF (pFB <> 0) THEN
    nResult := pFB^.Increase(nCountStep := nIncrease);
END_IF

IF bDelete THEN
    __DELETE(pFB);
    bDelete := FALSE;
END_IF

Sample with array:

MAIN program:

PROGRAM MAIN
VAR
    bNew        : BOOL := TRUE;
    bDelete     : BOOL;
    pArrayBytes : POINTER TO BYTE;
    nTest       : INT;
END_VAR
IF bNew AND (pArrayBytes = 0) THEN
    pArrayBytes := __NEW(BYTE, 25);
    bNew := FALSE;
END_IF

IF (pArrayBytes <> 0)THEN
    pArrayBytes[24] := 125;  // writing a value to the last array element
    nTest := pArrayBytes[24]
END_IF

IF bDelete THEN
    __DELETE(pArrayBytes);
    bDelete := FALSE;
END_IF