Welcome to our new forum
All users of the legacy CODESYS Forums, please create a new account at account.codesys.com. But make sure to use the same E-Mail address as in the old Forum. Then your posts will be matched. Close

Interface as Structure Element?

Anonymous
2014-01-21
2014-05-14
  • Anonymous - 2014-01-21

    Originally created by: Captive Engineer

    In working with a vendor's library (for SoMachine software which utilizes CoDeSys V3), I've come across a structure which contains an interface or perhaps an interface instance as one of its elements.

    If in my code I attempt to dot-reference a property of the interface inside the structure, something like . . .

    udi_Number := st_Big_Library_Structure.st_Smaller_Embedded_Structure.i_Embedded_Interface_Type.st_Address.udi_Number;
    

    the compiler fails with an error which reads:

    Zitat:
    [ERROR] MyProgram: Action_Initialize_Device PacDrive3: PLC Logic: Application: Main_Task_Call: C0185: It is not possible to perform component access '.', index access '[]', call '()' or dereference '^' on result of function call. Assign result to help variable first.
    Compile complete -- 1 errors, 0 warnings

    I would like to know how I should properly reference the property data when it is implemented this way.

    The broader question, though, is what would be the programmer's reason for using an interface in a structure? I see that it is also possible to compile a function block which uses an interface as an input! Presumably, there are similar reasons for supporting this functionality. The help files do not seem to cover these possibilities, however, so perhaps some of the experts here might offer an explanation.

    Kind regard,
    The Captive Engineer

     
  • Anonymous - 2014-01-22

    Originally created by: Captive Engineer

    After some more detailed experimentation, my problem shows up if a property is a structure and I attempt to reference the structure element through the property interface. For example . . .

    (* I make up some structure *)
    TYPE ST_Bespoke :
    STRUCT
        udi_My_UDINT  :  UDINT;
    END_STRUCT
    END_TYPE
    (* Then I make an interface using the ST_Bespoke structure, *)
    INTERFACE ITF_mit_Structure EXTENDS __SYSTEM.IQueryInterface
    (* and add a structure property. *)
    PROPERTY Structure_Prop  :  ST_Bespoke
    (* Now I make a Function Block which implements my new interface, *)
    FUNCTION_BLOCK FB_Test IMPLEMENTS ITF_mit_Structure
    (* and for this demonstration, FB variables are optional. *)
    (* Then in the running program POU, *)
    PROGRAM Main
    VAR
        iFB_Try    :    FB_Test;
        st_Try    :    ST_Bespoke;
        udi_Value    :    UDINT;
    END_VAR
    iFB_Try();
    udi_Value    :=    iFB_Try.Structure_Prop.udi_My_UDINT;  (*This assignment throws a compile error like that in the original post*)
    

    By experimentation, I have found one way to work around this dot-reference problem. That is to assign the whole structure property, instead of one of its elements, to a suitable variable. So the program code becomes . . .

    iFB_Try();
    st_Try    :=    iFB_Try.Structure_Prop;
    udi_Value    :=    st_Try.udi_My_UDINT;
    

    The issue is not really a problem with structures containing properties as I originally thought. The problem comes if a property is a structured type and the programmer tries to dot-reference it directly through the property interface. So now my question is whether there is a particular reason the language should want to discourage dot-referencing through properties, or if instead this is simply an unanticipated access technique that CoDeSys V3 will eventually support.

    Responses are welcome.

    Respectfully submitted,
    The Captive Engineer

     
  • Anonymous - 2014-05-14

    Originally created by: scott_cunningham

    I ran into this problem and solved it by using REFERENCE TO in the property. Then only define a GET - no SET is needed, even if you do write to the variables. You will get compile problems if you include the SET.

    Example: A remote IO module has 16 digital inputs and 16 digital outputs. Each input and output is it's own object (FB) with properties (Invert, State) and methods (TurnOn(), TurnOff(), Toggle()). The remoteIO object has two properties - 'Input' and 'Output' which access a structure of the 16 input or output objects. It is then desirable to have those properties and methods available with dot notation for the main remote IO module ('Bank1' in my example):

    JogMode:= Bank1.Input.D00.State;
    Bank1.Output.D00.State:= TRUE;
    Bank1.Output.D01.State:= Warning;
    

    The trick is in the property 'Output':

    TYPE T_DI16 :
    STRUCT
       D00: ClassDigitalInput;
       D01: ClassDigitalInput;
       ...
       D15: ClassDigitalInput;
    END_STRUCT
    END_TYPE
    TYPE T_DO16 :
    STRUCT
       D00: ClassDigitalOutput;
       D01: ClassDigitalOutput;
       ...
       D15: ClassDigitalOutput;
    END_STRUCT
    END_TYPE
    FUNCTION_BLOCK ClassRemoteIO_DIO16
    VAR
       _Input: T_DI16;
       _Output: T_DO16;
    END_VAR
    PROPERTY Input : REFERENCE TO T_DI16
       GET
          Input REF= _Input;
       END_GET
    END_PROPERTY
    PROPERTY Output : REFERENCE TO T_DO16
       GET
          Output REF= _Output;
       END_GET
    END_PROPERTY
    END_FUNCTION_BLOCK
    

    It is possible to use REFERENCE TO with any data types like arrays, FBs, simple types, structures.

    This is very, nearly, exactly, what I have wanted (OK, I'd really like to be able to drop the 'State' property and do 'Bank1.Output.D00:= TRUE;' and 'Bank1.Output.D00.Invert:= TRUE;' but FBs don't just return a BOOL!)

    Please note your access time when using properties - they are really a function call behind the scenes. So, in my example just using properties adds code calls - may be of importance with some hardware platforms/machines.

     

Log in to post a comment.