Property that returns REFERENCE TO Interface type?

2021-11-18
2021-11-23
  • thecolonel26 - 2021-11-18

    I have a property
    defined as

    PROPERTY PUBLIC LiveValue : REFERENCE TO IEngineeringValue
    

    I have a

    VAR _liveValue : EngValueBase; //(Which Implements IEngineeringValue)
    END_VAR
    

    I defined the Get for LiveValue as

    LiveValue REF= _liveValue;
    

    But I get the following build error
    C0032: Cannot convert type 'REFERENCE TO IEngineeringValue' to type'EngValueBase'

    Which seems like it is backwards and should say
    Cannot convert type 'EngValueBase' to type 'REFERENCE TO IEngineeringValue'

    but regardless what is going wrong here?

     

    Last edit: thecolonel26 2021-11-18
  • tvm - 2021-11-18

    I'm not clear on exactly what you're trying to do here, but creating a reference to the interface is not necessary. Just make your property of type IEngineeringValue, and in your property do

    LiveValue:= _liveValue
    

    the interface acts kind of a like a reference already

     
    • thecolonel26 - 2021-11-20

      Well what I am trying to do is to return a Reference to EngValueBase but using type IEngineeringValue so that the consumer doesn't care what the base class is. I plan to have different implementations of the EngValue later on which is why I want it to be behind an interface.

      I have tried using := instead of Ref= but I get a run time exception, of access violation.

       

      Last edit: thecolonel26 2021-11-20
      • i-campbell

        i-campbell - 2021-11-20

        an interface contains methods and properties.
        an instance of an interface, contains only a pointer. The compiler uses this pointer to know where to access the methods and pointers of the interface - which can only be, as you know, some function block which implements it.

        A reference again contains only a pointer. The compiler treats it differently though, and when you use the := operator, it copies the right hand side to the object behind the reference.

        So if you have a reference to interface.. it is like a double pointer. Your Reference tells you where in memory you can find a variable of type interface. This interface then tells you, where in memory you can find an instance of a function block.

        So you see, because you seem to only want one level of pointing, it would be sufficient for your property to return an IEngineeringValue, and use the := to assign it to another IEngineeringValue.

        The code you have in your opening post fails because... nowhere is there a variable of type IEngineeringValue, with which you can reference.

        tl;dr
        Reference, Interface and Pointer are all essentially the same thing, they store a memory location of some object. The difference is in the semantics of how you access the object, and how you update the memory location.

         
        • thecolonel26 - 2021-11-23

          Thank you very much. I think that is what I needed to know. I did not know that interfaces were passed by reference only. Knowing that now everything makes more sense.

           
  • hermsen

    hermsen - 2021-11-18

    actually, to me the whole pointer and the interface do not make sense, since a
    property can be regarded as a value, but this interface with only some engineering value do not make any sense at all.

    Maybe the folloing will help you understand my point better.

    An analog IO point could be reflected via some STRUCT like so.
    Such a struct is the output of an FB that scales an analog input or output channel;

    Analog.Raw ( unscaled IO input value)
    Analog.Value ( scaled between rangemin and max in eng unit)
    Analog.RangeMin
    Analog.RangeMax
    Analog.Unit ( engineering units of analog measurement )
    Analog.ChStatus ( contains the channel status )
    Analog.ValPerc ( scaled value between 0..100 % instead of eng units )
    Analog.Decimals (contains the prefered decimals when presenting this value)
    Analog.Forced ( by setting True we can force a user value instead of the channel value
    Analog.ForcedValue ( this value will overrule the IO value if forced is True)

    If I want to share this IO point struct, I could make this whole struct as a single get / set or some methods in an Interface, not just a single member out of the struct as a value in the interface.

    I hope you understand my point,

    good luck and have fun!

     
    • thecolonel26 - 2021-11-20

      I think you are incorrectly assuming what IEngneeringValue contains.

      Right now it has it's own Properties of Value and MeaUnitAsString.

      The intend is to have a mechanism in place so that different types of engineering values can be compared if they are of the same type, Like Temperature, could be compared if if one instance is of using Celsius and one instance using Fahrenheit etc.

      Further set points in the system will be stored in the same mechanism.

      So I have a very valid reason for want to but a complex type behind an interface early on.

       

Log in to post a comment.