0

I am attempting to implement the Observer design pattern in CoDeSys using structured text. I'm encountering an error where I can't call the ., [], nor [..] on an interface property. Is it possible to have an interface property that is an array? The interface property in question is the following:

PROPERTY observers : ARRAY[0..20] OF IObserver

And the interface structure follows the observer patter like the following.

enter image description here

The implementation of the notifyAllObservers method is the following.

METHOD notifyAllObservers
VAR 
   i : INT;
END_VAR

FOR i := 0 TO 20 DO
  CommandHandler.observers[i].update(CommandHandler.commands);
END_FOR

enter image description here enter image description here

Michael LeVan
  • 528
  • 2
  • 8
  • 21

4 Answers4

0

I think the problem with your CommandHandler.observers[i] is that you don't have any instances of anything implementing the IObserver. You cannot access your observers property the way you do since it is not an object.

If you delete the observers property, define an observer FB implementing the IObserver and then add an array of observer (FB) inside CommandHandler your notifyAllObservers code will work.

pboedker
  • 523
  • 1
  • 3
  • 17
0

You can't access the array fields that way.

There are several other ways you can achieve what you want in Structured Text:

  1. Since your property is public there is no reason not to declare the array of IObserver as an input field of the Function Block. If you do so you can access it the way you desire.

Declaration part:

FUNCTION_BLOCK CommandHandler
VAR_INPUT
    IObservers : ARRAY[0..19] OF IObserver;
END_VAR

Example call:

fbCommandHandler.IObservers[i].update();

  1. Another way is you access (and modifiy, etc..) your IObservers from inside the update method:

Create a new Interface IObserverArray with an update method:

METHOD update : BOOL
VAR_INPUT
    index : INT;
    cmd : INT;
END_VAR

Create a new Function Block implementing the IObserverArray itf:

FUNCTION_BLOCK ObserverArray IMPLEMENTS IObserverArray

//declaration part of the update method
METHOD update : BOOL
VAR_INPUT
    index   : INT;
    cmd : INT;
END_VAR
VAR
    itfObservers    : ARRAY [0..19] OF IObserver;
END_VAR

//imlementation part of the update method
itfObservers[index].update(cmd);

Create a method getObservers() in your CommandHandler Function Block that returns a IObserverArray:

METHOD getObservers : IObserverArray

//imlementation part of the getObservers method
getObservers := aObservers;

Now you just declare aObservers : ObserverArray; in your CommandHandler as a VAR and call it like this : fbCommandHandler.getObservers().update(5,12);

Filippo Boido
  • 1,136
  • 7
  • 11
0

https://help.codesys.com/api-content/2/codesys/3.5.12.0/en/_cds_operator_new/

_new(8,nLength +1)
Make a list with memcpy(new,old)
__DELETE(old);

Something like that should work!

John Conde
  • 217,595
  • 99
  • 455
  • 496
Slaud
  • 1
0

How did you set up the property observers?

If you just got an array of objects you are not able to access 1 of the array members individually. However if you only use a get action and instead of getting the array of observers, get a reference to an array of observers it will work. like so

PROPERTY PUBLIC observers : REFERENCE TO ARRAY[*Lower_Bound*..*Upper_Bound*] OF *Class to be returned*

In the get action set the following:

observers REF= *object to be returned*

In this way the getter wil return a pointer/reference instead of the object. With the reference you can reach for an individual item in the array.

Hope this helps

Alex
  • 3
  • 2