Skip to main content

Opérateur : __NEW

L'opérateur est une extension de la norme CEI 61131-3.

le __NEW L'opérateur réserve de la mémoire dynamique pour instancier des blocs fonctionnels, des types de données définis par l'utilisateur ou des tableaux de types standard. L'opérateur renvoie un pointeur typé correspondant.

Condition : Dans la boîte de dialogue des propriétés de l'application mère, sur le Options de création d'applications onglet, l'onglet Utiliser l'allocation de mémoire dynamique option est sélectionnée.

Syntaxe

<pointer name> := __NEW( <type> ( , <size> )? );
__DELETE( <pointer name> );

<type> : <function block> | <data unit type> | <standard data type>

L'opérateur génère une instance du type <type> et renvoie un pointeur vers cette instance. Ensuite, l'initialisation de l'instance est appelée. Si <type> est un type de données standard scalaire, puis l'opérande facultatif <size> est également évalué. Ensuite, l'opérateur génère un tableau de type <standard data type> et la taille <size>. Si la tentative d'allocation de mémoire échoue, alors __NEW renvoie la valeur 0.

Utilisez l'opérateur dans l'affectation ":=" ; sinon, un message d'erreur s'affiche.

Un bloc fonctionnel ou un type de données défini par l'utilisateur dont l'instance est créée dynamiquement avec __NEW utilise une zone mémoire fixe. Ici, il est nécessaire que vous marquiez les objets avec le pragma {attribute 'enable_dynamic_creation'}. Il n'est pas nécessaire pour les blocs fonctionnels faisant partie d'une bibliothèque.

Astuce

Si vous modifiez la disposition des données du bloc fonctionnel en mode en ligne, vous ne pouvez pas exécuter une connexion avec une modification en ligne par la suite. En effet, la zone mémoire de l'instance du bloc fonction a été invalidée. Vous modifiez la disposition des données lorsque vous ajoutez de nouvelles variables au bloc fonction, supprimez des variables existantes ou modifiez les types de données des variables.

Exemple 150. Exemple

Déployer (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

Bloc fonction

{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

Type de données défini par l'utilisateur (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

Tableau (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


Important

Nous déconseillons l'exécution simultanée de deux tâches qui appellent toutes deux le __NEW opérateur. Vous utilisez soit un sémaphore (SysSemEnter) ou une technique comparable pour empêcher un appel simultané de __NEW. Cependant, cela se traduit par une gigue plus élevée lorsque __NEW est largement appliqué.

Nous vous recommandons d'appeler __NEW opérateurs dans une seule tâche.