Calling a Method
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 specifier, a method can be called only within its own namespace (INTERNAL
), only within its own POU and its derivatives (PROTECTED
), or only within its own POU (PRIVATE
). For PUBLIC
, the method can be called from anywhere.
Within the implementation, a method can recursively call itself, 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.
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.
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
The function blocks fub1
and fub2
extend the function block fubbase
and implement the interface interface1
. The method1
and method2
applications 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 "Function" topic.
Syntax for calls
<function block name>.<method name>(<first input name> := <value> (, <further input assignments>)+ , <first output name> => <first output variable name> (,<further output assignments>)+ );
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, then CODESYS processes the method even if the active application is currently in the STOP state:
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^.udState = 1 THEN <instructions> END_IF;
Calling methods recursively
Tip
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
pointerIndirectly 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' := '<estimated stack size in bytes>'}
, then the compiler warning is suppressed. For an implementation example, see the 'estimated-stack-usage' Attribute chapter.