To implement a method call, the actual parameters (arguments) are passed to the interface variables. As an alternative, the parameter names can be omitted.
Depending on the declared access modifier, a method can be called only within its
own namespace (INTERNAL
), only within its own programming module and its derivatives (PROTECTED
), or only within its own programming module (PRIVATE
). For PUBLIC
, the method can be called from anywhere.
Within the implementation, a method can call itself recursively, either directly by
means of the THIS
pointer, or by means of a local variable for the assigned function block.
Method call as a virtual function call
Virtual function calls can occur due to inheritance.
Virtual function calls enable one and the same call to call various methods in a program source code during the runtime.
In the following cases the method call is dynamically bound:
-
You call a method via a pointer to a function block (for example
pfub^.method
).In this situation the pointer can point to instances of the type of the function block and to instances of all derived function blocks.
-
You call the method of an interface variable (for example
interface1.method
).The interface can refer to all instances of function blocks that implement this interface.
-
A method calls another method of the same function block. In this case the method can also call the method of a derived function block with the same name.
-
The call of a method takes place by means of a reference to a function block. In this situation the reference can point to instances of the type of the function block and to instances of all derived function blocks.
-
You assign
VAR_IN_OUT
variables of a basic function block type to an instance of a derived FB type.In this situation the variable can point to instances of the type of the function block and to instances of all derived function blocks.
Example
Overloading methods
The function blocks fub1
and fub2
extend the function block fubbase
and implement the interface interface1
. The methods method1
and method2
exist.
PROGRAM PLC_PRG VAR_INPUT b : BOOL; END_VAR VAR pInst : POINTER TO fubbase; instBase : fubbase; inst1 : fub1; inst2 : fub2; instRef : REFERENCE to fubbase; END_VAR IF b THEN instRef REF= inst1; (* reference to fub1 *) pInst := ADR(instBase); ELSE instRef REF= inst2; (* reference to fub2 *) pInst := ADR(inst1); END_IF pInst^.method1(); (* If b is TRUE, fubbase.method1 will be called, otherwise fub1.method1 is called *) instRef.method1(); (* If b ist TRUE, fub1.method1 will be called, otherwise fub2.method1 is called*)
On the assumption that fubbase
in the above example contains two methods method1
and method2
, it overwrites fub1 method2
, but not method1
. The call of method1
takes place as follows:
pInst^.method1()
;
If b
is TRUE, then CODESYS calls fubbase.method1
. If not, then fub1.method1
is called.
Additional outputs
In accordance with the IEC 61131-3 standard, methods can have additional outputs declared, like normal functions. With the method call, you assign variables to the additional outputs.
Detailed information about this can be found in the topic “Function”.
Syntax for the call:
<function block name>.<method name>(<first input name> := <value> (, <further input assignments>)+ , <first output name> => <first output variable name> (,<further output assignments>)+ );
Example
Declaration
METHOD PUBLIC DoIt : BOOL VAR_INPUT iInput_1 : DWORD; iInput_2 : DWORD; END_VAR VAR_OUTPUT iOutput_1 : INT; sOutput_2 : STRING; ENDVAR
Call
fbInstance.DoIt(iInput_1 := 1, iInput_2 := 2, iOutput_1 => iLocal_1, sOUtput_2 => sLocal_2);
When the method is called, the values of the method outputs are written to the locally declared output variables.
Calling a method even if the application is in the STOP state
In the device description it is possible to define that a certain function block instance (of a library function block) always calls a certain method in each task cycle. If the method contains the input parameters of the following example, CODESYS processes the method even if the active application is presently in the STOP state:
Example
VAR_INPUT pTaskInfo : POINTER TO DWORD; pApplicationInfo: POINTER TO _IMPLICIT_APPLICATION_INFO; END_VAR (*Now the status of the application can be queried via pApplicationInfo and the instructions can be implemented: *) IF pApplicationInfo^.state = RUNNING THEN <instructions> END_IF;
Calling methods recursively
Use recursions mainly for processing recursive data types such as linked lists. Generally, we recommend that you be careful when using recursion. An unexpectedly deep recursion can lead to stack overflow and therefore to machine downtime.
Within their implementation, a method can call itself:
-
Directly by means of the
THIS
pointer -
Indirectly by means of a local function block instance of the basic function block
Usually, a compiler warning is issued for such a recursive call. If the method is
provided with the pragma {attribute 'estimated-stack-usage' := '<sstimated_stack_size_in_bytes>'}
, then the compiler warning is suppressed. For an implementation example, refer to
the section "Attribute 'estimated-stack-usage'".