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

Why aren't FunctionBlocks passed by reference by default?

2022-07-14
2022-07-15
  • thecolonel26 - 2022-07-14

    Being pretty experience with C# I find this to be baffling. IN C# All Objects are passed by reference, but structures are not. In what cases would would want to pass a function block by value? I have never found myself wanting to do this. Now Structs sure I can see wanting to pass those by value, and that is also how they behave in C#.

    Can anyone shed some light on the rational for this behavior?

     

    Last edit: thecolonel26 2022-07-14
  • hermsen

    hermsen - 2022-07-14

    VAR_INPUT
    used for passing by value (except when using a pointer, a reference or an interface as a var_input)

    VAR_IN_OUT
    passes by Reference, mainly used for passing FB's, but I'd personally opt for an interface via VAR_INPUT and let the interface expose a pointer to its Instance.

    VAR INPUT and VAR IN OUT and VAR OUTPUT are standardized ways of getting information in and or out, next to Interfaces.
    This is as defined by the IEC 61131-3 Norm for industrial automation. Industrial automation has different needs because it is a different usage domain (i.e. stricter) then say C# or Python.

    I hope this may shed light on your question.

    PS offcourse passing by reference is much wiser when using i.e. FB's structs, array's or strings.

     

    Last edit: hermsen 2022-07-14
  • fajean - 2022-07-14

    I develop everything in structured text, with no desire to make my function blocks amenable to use in the visual languages. Maybe someone working in ladder all the time has a use for passing FBs by value that I do now know of, but I could really not tell.

    The way I develop, I would rather have function blocks passed by reference by default. I do not remember ever passing a FB by value, or using the assignment operator on a FB (instead of REF= which I use very, very heavily). In fact, I default to adding the "{attribute 'no_assign'}" pragma at the top of every function block I create to ask for the compiler's help in pointing out any case where I would let a ":= " slip by mistake.

    Why was that choice made? Well, I guess it is cleaner in a certain sense : function blocks are essentially structures bundled with functions, and structures are passed by value by default (which might well dates back to before the language had OO extensions, but I do now know the history). If you were to pass function block instances by reference, then you would need an additional keyword to force passing by value in the rare case where you really need to. Maybe it is a case where day-to-day use and language design purity are not aligned, and the purists won this one.

     
    • thecolonel26 - 2022-07-14

      {attribute 'no_assign'} is a good tip

      I mean, needing to pass by value is so rare, you could just build you own Clone Method, where you pass, the instance and then copy it member my member to a different instance.

      this is the norm in C#

       
  • thecolonel26 - 2022-07-14

    So if your FB implements say InterfaceA and you set your Input as type InterfaceA it will pass by reference?

    I hope this may shed light on your question.

    PS offcourse passing by reference is much wiser when using i.e. FB's structs, array's or strings.

    I honestly not really because as you point out, it IS usually wiser to pass them by reference.

    but I guess IEC saying so makes sense why codesys does it this way, but not why IEC 61131-3 says to do it this way.

    I would love to have a copy of IEC 61131-3 but it is waaaaaaaaaaaay to expensive to buy just for curiousity sake.

    Side Note: The other annoying thing I have encounter is that you can't have an array of references which is seriously annoying, I try to avoid pointer and just use References.

     

    Last edit: thecolonel26 2022-07-14
  • hermsen

    hermsen - 2022-07-14

    VAR_INPUT etc
    If you come from an OOP language (C++, C#), VAR_INPUT etc would probably make less sense then for someone who comes from procedural languages(C, Pascal). Pure classes do not have VAR_INPUT or VAR_OUTPUT etc as far as I remember, as they only posses Methods/Properties and interfaces to gain access to the local memory in the class. procedural languages don't use classes but Procedures and Functions (i.e Function blocks and Functions). VAR_INPUT/ VAR_OUT etc has found its way into IEC61131-3 by since its first iteration back in the 90's since Procedural programming was the norm. The syntax is heavily lifted from Pascal. OOP was allready around but in that era it made no sense yet to the Machine Automation Domain. Things surely have evolved since that time.

    "So needing to pass by value is so rare" => I disagree with this, many programmers use it for inputs of FB's methods and properties all the time, except when dealing with large chunks of memory in favor to optimize for speed, for which we pass by reference, in which case we can use a plethora of tricks to achieve that. Maybe we are having a babylonic speech difference here?

    Also, do dive into Functional Programming and you will see that "Pass by Value" is a strict norm for that paradigm from which no deviation is possible. Too bad that paradigm is fairly unusable in the PLC programming domain as it features some interesting things like "no side-effects" through intensive usage of "var by ref". Every function takes inputs as constants and passes the result(s) as a new variable. Quite memory intensive but also very clean and arguably very quick.

    Anyway I deviate too much from the real topic.

     

    Last edit: hermsen 2022-07-14
    • thecolonel26 - 2022-07-15

      "So needing to pass by value is so rare" => I disagree with this, many programmers use it for inputs of FB's methods and properties all the time, except when dealing with large chunks of memory in favor to optimize for speed, for which we pass by reference, in which case we can use a plethora of tricks to achieve that. Maybe we are having a babylonic speech difference here?

      No I think you misunderstood what I was saying.

      I am not saying all inputs should be passed by reference instead of passed by value. I am saying that only FB instances should be passed by reference.

      If you have FB_A type and FB_B type and FB_B needs access an instance of FB_A it doesn't make any sense to copy the whole instance in to FB_B, you are wasting memory and you usually want to mutate (change it) the instance that was passed in, you would either use VAR_IN_OUT or use VAR_INPUT of Reference. but I can't imagine a scenario where you would want to pass the FB instance in by value.

      All other data types should default to pass by value, such as INTs, Reals, BOOLs, ENUMs, Structs, etc.

      Does that make sense?

       

      Last edit: thecolonel26 2022-10-02
      • hermsen

        hermsen - 2022-07-15

        Yes I see what you try to say but I don not agree to letting the compiler enforce a default pass by ... on based on a datatype or fb etc. This kind of enforcing diminishes the power of freedom to chose and introduces added complexity to override the default compiler behaviour with yet another pragma or so. The language provides many ways to accomodate "var by ref" without needless enforcing you. You can do it straight from the language without any compiler bending.

         

        Last edit: hermsen 2022-07-15

Log in to post a comment.