** TLDR; Is it possible to create pointers to methods, store them and then call them? **
This question is related to this question: how to create pointer to function in codesys v3, but my question is about methods, and, since the referenced question is +5 years old, other solutions might be at hand.
The code below does not work, but it gives an impression of what I am trying to do, and how I expected it to work.
Let's say I have an FB/class: Alarm
, in which I want to inject a call-back into Alarm.ActivateCallback
that is to be executed upon activation of the alarm, using Alarm.Activate()
. PLC_PRG has an instance of the Alarm
and wants to inject a method PRG.OnAlarm1Activated()
as the call-back, that, for now, just sets a bool of the PRG to TRUE:
FB Alarm
FUNCTION_BLOCK Alarm
VAR_INPUT
ActivateCallback : POINTER TO CallbackDelegate;
END_VAR
Alarm.Activate()
IF (ActivateCallback <> 0) THEN
ActivateCallback^();
END_IF;
PLC_PRG:
PROGRAM PLC_PRG
VAR
_init : BOOL := TRUE;
_activate : BOOL := FALSE;
_alarm1 : Alarm;
_alarm1Activated : BOOL;
END_VAR
IF (_init) THEN
_alarm1.ActivateCallback :=ADR(OnAlarm1Activated);
_init := FALSE;
END_IF
IF (_activate) THEN
_alarm1.Activate();
END_IF
PLC_PRG.OnAlarm1Activated():
Alarm1Activated := TRUE;
For the code above, I get the following errors:
- 'CallbackDelegate' is of type FUNCTION and cannot be instantiated
- Operation 'Adr' is not possible on 'OnAlarm1Activated'
Can the code above be modified to enable the desired functionality?
As an alternative, I can use interfaces and inject these. But I would also like to know whether the above is possible as well.
Side-note: CODESYS help states the following, but maybe there is a work-around:
... CODESYS offers no possibility to call a function pointer within an application in the programming system! ...
EDIT to ellaborate more on the interface alternative (excuse my C#/CODESYS hybrid semi-code)
public enum AlarmEvent
{
Activated,
Cleared,
}
public FB Alarm
{
public AlarmHandler : REFERENCE TO IAlarmEventHandler;
public Activate() {
AlarmHandler.HandleAlarmEvent(this, AlarmEvent.Activate);
}
}
public interface IAlarmEventHandler
{
public void HandleAlarmEvent(ref Alarm alarm, AlarmEvent event);
}
public FB PLC_PRG : IAlarmEventHandler
{
Alarm1 : Alarm;
public FB_Init() {
Alarm1.AlarmHandler := this;
}
public void HandleAlarmEvent(ref Alarm alarm, AlarmEvent event) {
if (alarm == Alarm1 && event == AlarmEvent.Activated)
_alarm1Activated = true;
}
}