__NEW

Définition

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.

Syntaxe

__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.

Exemple

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