inheritance / extending a datatype

Stefan
2020-05-01
2020-05-17
  • Stefan - 2020-05-01

    Hi,

    I'm trying to pass an array of an extended datatype as a VAR_IN_OUT to a funtionblock:

    I have a struct "Object":

    TYPE Object :
    STRUCT
        Position: INT := -1;
        Width: INT;
    END_STRUCT
    END_TYPE
    

    and i have an extended object "Box":

    TYPE Box EXTENDS Object :
    STRUCT
        Color: INT;
    END_STRUCT
    END_TYPE
    

    I would like to pass an array of all kinds of object to a functionblock, for example:

    FUNCTION_BLOCK MoveObjects
    VAR_INPUT
    END_VAR
    VAR_OUTPUT
    END_VAR
    VAR_IN_OUT
        objects: ARRAY[*] OF Object;
    END_VAR
    VAR
    END_VAR
    

    But when i try to pass an array of boxes, i get a compile error:

    PROGRAM PLC_PRG
    VAR
        boxes: ARRAY[0..9] OF BOX;
        moveObj: MoveObjects;
    END_VAR
    
    moveObj(objects := boxes);
    

    Last line gives me a "cannot convert type 'ARRAY[0..9] OF BOX' to type 'ARRAY[*] OF Object'. The error is not about the size of the array (0..9 vs *), but about the box and object.
    How do i solve this?

     
  • JAPIB

    JAPIB - 2020-05-02

    Hi,

    "cannot convert type 'ARRAY[0..9] OF BOX' to type 'ARRAY[*] OF Object"

    I think the error is that you try to transfer an ARRAY of BOX into an ARRAY of Object.
    But a BOX contains 3 elements (Position, Width, Color) and an Object contains only 2 elements (Position, Width) ! System don't know what to do with "Color" !!
    You have to use a same type of ARRAY, or to transform Object type into Box Type.

    For example :

    FUNCTION_BLOCK Transform_Object_To_Box
    VAR_INPUT
    END_VAR
    VAR_OUTPUT
    END_VAR
    VAR_IN_OUT
    aObject: ARRAY[*] OF Object; (source table)
    aBox:ARRAY[*] OF Box; (destination table)
    END_VAR
    VAR
    iIndice:DINT; (Work index)
    diBegin:DINT; (Start of table)
    diEnd:DINT; (End of table)
    END_VAR
    (FB code)
    (Calculation of the dimensions of the table)
    diBegin:=LOWER_BOUND(aObject,1);
    diEnd:=UPPER_BOUND(aObject,1);

    (Copy source table to destination table)
    FOR iIndice:= diBegin TO diEnd DO
    aBox[iIndice].Position:=aObject[iIndice].Position;
    aBox[iIndice].Width:=aObject[iIndice].Width;
    aBox[iIndice].Color:=0;
    END_FOR


    PROGRAM PLC_PRG
    VAR
    aInboxes: ARRAY[0..9] OF Box; (destination table)
    aInObjects: ARRAY[0..9] OF Object; (source table)
    Transform: Transform_Object_To_Box;
    END_VAR

    (PLC_PRG code)
    Transform(aObject:=aInObjects , aBox:=aInboxes );

    BR

     

    Last edit: JAPIB 2020-05-02
  • Stefan - 2020-05-03

    isn't the whole point of extending a struct that an object of the extended struct is also considered as an object of the base struct?

    In my example, I want 1 fucntionblock to move objects. I would like this functionblock to be reusable to move any kind of object, either base or extended. I don't need the color of the box to move it.

    Instead of using your solution, where an array of boxes is converted into an array of objects, I can just as well write a second functionblock moveBoxes, defeating the whole point of extending my object...

    Note that if I create a functionblock MoveObject that moves 1 object, this idea holds:

    FUNCTION_BLOCK MoveObject
    VAR_INPUT
        object: Object;
    END_VAR
    VAR_OUTPUT
    END_VAR
    VAR
    END_VAR
    

    and

    PROGRAM PLC_PRG
    VAR
        boxes: ARRAY[0..9] OF BOX;
        moveObjects: MoveObjects;
        moveObject: MoveObject;
    END_VAR
    
    //moveObjects(objects := boxes);
    moveObject(object := boxes[0]);
    

    It is only when i start using arrays that it does not work anymore

     
  • Stefan - 2020-05-03

    ok, so an array puts the different objects directly behind each other in memory, so it is not possible to change the size (add or remove properties) of the individual object. I figured this out after trying the same thing in c++.

    BUT... even with an array of pointers to an object, it does not work... This should work, no?

     
    • aliazzz

      aliazzz - 2020-05-03

      There are some caveats on OOP usage in automation (PLC/DCS) systems. One of those is instantiation of objects in runtime, which is possible, but should be handled with extra care.

      On my git (not yest hosted on forge... sry)
      https://github.com/Aliazzzz/OOP-Concept-Examples-in-CODESYS-V3
      (just basics, no fancy stuff)

       

      Last edit: aliazzz 2020-05-03
  • JAPIB

    JAPIB - 2020-05-03

    My previous remark is still right, and you saw it with your example in C++
    In any case, even with a pointer, if you try to move an array into another (whatever the type of data), the destination array must have the same structure as the source array.
    When you use only the first source table level, it works well, because system take the two first element ( Position and Width) and forget the third, because destination table consist of 2 elements.
    But when you use the entire table, system don't know how to fill destination table, because structures are different.

     
  • Stefan - 2020-05-17

    I ended up using a array of interfaces. Not intirely happy because i still need 2 array's (one for the objects, an other one for the interfaces), but it works

    @aliazz: I really liked your git repository on OOP concepts. Thanks!

     

    Last edit: Stefan 2020-05-17

Log in to post a comment.