'Overloading' functions with extended structs

I was wondering if overloading functions in TwinCAT was possible, but I found out that this is not the case. I did however realize that overloading is possible using a few work-arounds. In this article I’ll show how to mimic this behavior with extended structs.

What is overloading

Overloading a function means that you can call a function with an identical name, but it can have a different number of arguments. Also the data type of the arguments and/or the return type can differ. Some programming languages support more overloading types then others, as you can see here in this overview.

An example of overloading in C# would be the following. The function Rectangle can be called using a either a single int argument (making it a square), or it can be called using two float arguments. Furthermore the single argument function returns an int, whereas the two argument one returns a float.

public static class Area
{
    public static int Rectangle(int a)
    {
        return a * a;
    }

    public static float Rectangle(float a, float b)
    {
        return a * b;
    }
}

Many methods in C# are overloaded. See for example the Sum method with an impressive 20 overloads!

‘Overloading’ using structs

Jakob Sagatowski showed in his post “The wonders of any” that you can call a single function with different data types. In order to make this work he uses ANY.

You can also use extended structs to have a single function which accepts multiple structs which use the same base struct. For example we have a Point struct with a x and a y coordinate.

TYPE Point :
STRUCT
    x : REAL;
    y : REAL;
END_STRUCT
END_TYPE

And an extension of this struct which can also hold the time and a date.

TYPE TimePoint EXTENDS Point :
STRUCT
    t : DT;
END_STRUCT
END_TYPE

Then we make a function which calculates the distance of this point with respect to the origin at (0, 0).

FUNCTION Length : LREAL
VAR_INPUT
    point : Point;
END_VAR

Length := SQRT(EXPT(point.x, 2) + EXPT(point.y, 2));

Finally we call the method on two different points. One which is of type Point and the second which is of type TimePoint.

PROGRAM MAIN
VAR
    point1 : Point := (x:=2, y:=5);
    point2 : TimePoint := (x:=6, y:=7, t:=DT#2000-03-02-1:0);
    length1 : LREAL;
    length2 : LREAL;
END_VAR

length1 := Length(point1);
length2 := Length(point2);

When we run this program we can see that it calculated the length for both points.

Using this trick you can prevent having to write/test the same function multiple times. I couldn’t find any mention of this possibility on InfoSys, so I just tried it out. I was a bit surprised and relieved that it worked!

Discuss: r/plc & r/TwinCAT

❮ Unit testing code from a separate project
Source control tips for TwinCAT ❯
Like my work? Consider a donation!