Vai al contenuto

Question about object polymorphism

Home Forum Programmazione IEC 61131 (LogicLab) Question about object polymorphism

Stai visualizzando 5 post - dal 1 a 5 (di 5 totali)
  • Autore
    Post
  • #82249
    George
    Partecipante

    Is it possible to assign dynamically a FB pointer to an Interface type ?

    #82251
    Sergio Bertana
    Amministratore del forum

    Yes, also in LogicLab as in many modern IEC 61131-3 environments such as TwinCAT 3, Codesys v3.x, it is possible to dynamically assign a Function Block (FB) to a variable of interface type, provided that the FB implements that interface. The idea is that you can use an interface as an abstract type and dynamically assign an FB that implements it usually through pointer dereferencing (^) or a type cast.

    You can download Polymorphism a LogicLab program with an example of use the polymorphism, essentially referring to the screenshot yo can see the Form interface that refer to a trigonometric figure that has two method prototypes.

    • Area: This method calculates the area of the form
    • Perimeter: This method calculates the perimeter of the form

    Then two FBs are been defined each implement the Form interface, with the code to calculate the perimeter and area of the relate trigonometric figure. In the FBReference program the RForm variable of Form interface type is istantiated. Then by referencing RForm to different trigonometric figure is possible to calculate perimeter and area of them.

    #82260
    George
    Partecipante

    If I would instantiate Square and Rectangle FBs dynamically (SysMalloc) as the example

    IF (SysFirstLoop) THEN
        MySquare:=SysMAlloc(SIZEOF(Square));
        MyRectangle:=SysMAlloc(SIZEOF(Rectangle));
    
        @MySquare.Side:=10; //Square side
    
        @MyRectangle.Width:=20; //Rectangle width
        @MyRectangle.Height:=4; //Rectangle height
    END_IF;

    is it possible?

    #82272
    Sergio Bertana
    Amministratore del forum

    I’ve rewritten your program in a form I supposed was correct but there’s two compiling errors.

    VAR
        SquareArea : REAL; (* Square area *)
        SquarePerimeter : REAL; (* Square perimeter *)
        RectangleArea : REAL; (* Rectangle area *)
        RectanglePerimeter : REAL; (* Rectangle perimeter *)
        RForm : Form; (* Reference to Form *)
        MySquare : Square^; (* Reference to Square *)
        MyRectangle : Rectangle^; (*  Reference to Rectangle *)
    END_VAR
    
        // Program initializations.
    
        IF (SysFirstLoop) THEN
    //        MySquare:=SysMAlloc(SIZEOF(Square));
    //        MyRectangle:=SysMAlloc(SIZEOF(Rectangle));
    
            MySquare^.Side:=10; //Square side
    
            MyRectangle^.Width:=20; //Rectangle width
            MyRectangle^.Height:=4; //Rectangle height
        END_IF;
    
        // Calculates area and perimeter.
    
        RForm:=MySquare^; //Reference to Form
        SquareArea:=RForm.Area(); //Square area
        SquarePerimeter:=RForm.Perimeter(); //Square perimeter
    
        RForm:=MyRectangle^; //Reference to Form
        RectangleArea:=RForm.Area(); //Rectangle area
        RectanglePerimeter:=RForm.Perimeter(); //Rectangle perimeter

    I’ve to ask to Axel support how to manage this  scenario.

    I’ve a question, why you would dynamically instantiate the FBs? Is not easiest simply instantiate they in the data memory?

    #82315
    George
    Partecipante

    PROGRAM FBReference1

    VAR
    SquareArea : REAL; (* Square area *)
    SquarePerimeter : REAL; (* Square perimeter *)
    RectangleArea : REAL; (* Rectangle area *)
    RectanglePerimeter : REAL; (* Rectangle perimeter *)
    RForm : Form; (* Reference to Form *)
    MySquare : Square; (* Square form *)
    MyRectangle : Rectangle; (* Rectangle form *)
    pMySquare : @Square;
    pMyRectangle : @Rectangle;
    END_VAR

    IF (SysFirstLoop) THEN
    CASE select OF
    1:
    pMySquare:= SysMAlloc(SIZEOF(Square));
    RForm:=@pMySquare; //Reference to Form
    2:
    pMyRectangle:= SysMAlloc(SIZEOF(Rectangle));
    RForm:=@pMyRectangle; //Reference to Form
    END_CASE;
    END_IF;

    CASE select OF
    1:
    SquareArea:=RForm.Area(); //Square area
    SquarePerimeter:=RForm.Perimeter(); //Square perimeter
    2:
    RectangleArea:=RForm.Area(); //Rectangle area
    RectanglePerimeter:=RForm.Perimeter(); //Rectangle perimeter
    END_CASE;

    In TWINCAT we could write
    pMySquare:= _NEW(Square);
    RForm:= pMySquare^;
    RForm.Area();
    RForm.Perimeter();

Stai visualizzando 5 post - dal 1 a 5 (di 5 totali)
  • Devi essere connesso per rispondere a questo topic.