Cet opérateur n'est pas défini par la norme IEC 61131-3.
L'opérateur __NEW attribue de la mémoire aux instances de bloc fonction ou aux tableaux ayant des types de données standard. Il renvoie un pointeur de type approprié indiquant l'objet. Un message s'affiche lorsque l'opérateur ne figure pas dans une attribution.
Activez l'option Utiliser l'allocation dynamique de la mémoire dans l'affichage Options de création d'application (Affichage > Propriétés… > Options de création d'application) pour utiliser l'opérateur __NEW. Veuillez consulter le Guide de programmation spécifique à votre contrôleur pour savoir si votre contrôleur offre ces options.
Si aucune mémoire n'a pu être attribuée, __NEW renvoie 0.
Pour annuler l'attribution, utilisez __DELETE.
__NEW (<type>, [<taille>]
L'opérateur crée un objet de type <type> et renvoie un pointeur vers ce <type>. L'initialisation de l'objet est appelée après sa création. Une valeur 0 signifie que l'opération a échoué.
NOTE : utilisez le type de données du bloc fonction dérivé, et non celui du bloc fonction de base. N'utilisez pas une variable de type POINTER TO BaseFB. En effet, si le bloc fonction de base n'implémente aucune fonction FB_Exit, aucun bloc FB_Exit n'est appelé lors d'une prochaine utilisation de __DELETE(pBaseFB).
Lorsque <type> est scalaire, l'opérande facultatif <length> doit être défini en sus. L'opérateur crée alors un tableau des types scalaires de la taille indiquée.
pScalarType := __New(ScalarType, length);
NOTE : un bloc fonction créé avec __NEW est associé à une zone de mémoire fixe. Il est impossible de modifier la disposition des données via un changement en ligne. Autrement dit, vous ne pouvez pas ajouter ni supprimer de variables, et la modification des types est interdite.
Par conséquent, l'opérateur enable_dynamic_creation ne prend en charge que les blocs fonction issus de bibliothèques (non modifiables) et des blocs fonction contenant l'attribut __NEW. Un message s'affiche si un bloc fonction portant cet indicateur vient à changer, obligeant ainsi de recourir à un code de copie.
NOTE : Le code d'attribution de la mémoire doit être non réentrant.
Un sémaphore (SysSemEnter) empêche l'attribution de mémoire par deux tâches simultanées. Par conséquent, un usage intensif de __New risque d'augmenter la gigue.
Exemple avec un type scalaire :
TYPE DUT :
STRUCT
a,b,c,d,e,f : INT;
END_STRUCT
END_TYPE
PROGRAM PLC_PRG
VAR
pDut : POINTER TO DUT;
bInit: BOOL := TRUE;
bDelete: BOOL;
END_VAR
IF (bInit) THEN
pDut := __NEW(DUT);
bInit := FALSE;
END_IF
IF (bDelete) THEN
__DELETE(pDut);
END_IF
Exemple avec un bloc fonction :
{attribute 'enable_dynamic_creation'}
FUNCTION_BLOCK FBDynamic
VAR_INPUT
in1, in2 : INT;
END_VAR
VAR_OUTPUT
out : INT;
END_VAR
VAR
test1 : INT := 1234;
_inc : INT := 0;
_dut : POINTER TO DUT;
END_VAR
out := in1 + in2;
PROGRAM_PLC_PRG
VAR
pFB : POINTER TO FBDynamic;
loc : INT;
bInit: BOOL := TRUE;
bDelete: BOOL;
END_VAR
IF (bInit) THEN
pFB := __NEW(FBDynamic);
bInit := FALSE;
END_IF
IF (pFB <> 0) THEN
pFB^(in1 := 1, in2 := loc, out => loc);
pFB^.INC();
END_IF
IF (bDelete) THEN
__DELETE(pFB);
END_IF
Exemple avec un tableau :
PLC_PRG(PRG)
VAR
bInit: BOOL := TRUE;
bDelete: BOOL;
pArrayBytes : POINTER TO BYTE;
test: INT;
parr : POINTER TO BYTE;
END_VAR
IF (bInit) THEN
pArrayBytes := __NEW(BYTE, 25);
bInit := FALSE;
END_IF
IF (pArrayBytes <> 0) THEN
pArrayBytes[24] := 125;
test := pArrayBytes[24];
END_IF
IF (bDelete) THEN
__DELETE(pArrayBytes);
END_IF