I am new to twincat3 and especially using it with oop. I am trying to pass an instance of FB_EventLogger to the FB_init of an instance of O2_Sensor. Forexample: Main Var EventLogger : FB_EventLogger (I_PersistantEventStrotagr := CSV); O2_sensor : O2_Sensor(EventLogger := EventLogger); end_var
end_Main
O2_Sensor var EventLogger : Reference to FB_EventLogger ; eventinfo : something; end_var
method_addEvent
Eventlogger.AddEvent(eventinfo); end_method_addEvent
end_O2_Sensor
I would like to allow for any instance of the O2_sensor FB to be able to create their own event as this will make the code much better rather than having a seperate function that checks all the different inputs and then raises alarms or sents messages.
The First thing I thought about was to pass the instance of eventlogger fb and use that in the sensor's fb but that does not work. However, it works if I create a method that takes in a reference to an event logger, in other words O2_Sensor.addevent(EventLogger).
I am unable to fully understand your attempt reading your question. Initialization can be very tricky. Here are a few pointers :
The FB_Init of en enclosing function block instance is called after the FB_Init of nested function blocks it contains. You cannot pass as an argument to the FB_Init of a nested function block anything that is set by the enclosing function block's own FB_Init.
However, when using inheritance, if CHILD_FB extends PARENT_FB, then variables assigned in PARENT_FB.FB_Init can be used as arguments to the nested function blocks of CHILD_FB. You can therefore go around the limitation by introducing a level of inheritance. A bit more code, but it is easy code to write, and saves worse ugliness elsewhere.
Please note that you can use the "THIS" pointer as an argument to embedded function block instances, and the pointer is valid at the time the embedded instance's FB_Init is called. The pointer is valid (and can be used for reference injection), but calling methods on it is not intrinsically guaranteed to work (see next point).
Because you can receive a valid reference (or pointer) to an instance does not mean you can execute arbitrary methods on it, because those methods may rely on something that is not ready yet. It does not mean it cannot work either : the code can be called, and "plain" variables (i.e. not function blocks) and (potentially nested) arrays/structures of plain variables are usable.
I make heavy use of reference injection, I use FB_Init for assignments (including reference assignments), but not to call methods, unless I know those methods use only plain variables or structures of the same instance. This makes FB_Init independent of initialization order (very important for me, your mileage may vary).
Due to when/how FB_Init is executed, you cannot step into code it contains or calls. Bugs in FB_Init are therefore very difficult to debug, and doing only simple things helps avoid frustrating debugging sessions.
You may need, or benefit from, an initialization mechanism separate from FB_Init to finish the job. I have a whole framework that manages this for me (initialization and execution too), doing it "by hand" on anything complex is probably going to be a nightmare to develop and maintain.