OOP Access to #uses in class initialize doesn\'t work - should it?

Discussions about product bugs & problems!
Note: This is no replacement for the Official ETM Support!
8 posts • Page 1 of 1
leonmf
Posts:6
Joined: Mon Aug 11, 2014 6:21 pm

OOP Access to #uses in class initialize doesn\'t work - should it?

Post by leonmf »

Good afternoon,

I've been tracking down an issue for the last few hours and I think I finally understand the exact issue. What I don't understand is whether it is expected behavior and what I should consider in working around it.

I have a GlobalControl.ctl file tht contains the following:

dyn_string doorStatusList = makeDynString("Emergency Mode", "Estop", "Error", "Undefined", "Stopped", "Stopping", "Opening", "Closing", "Open", "Closed");


----------------------------


I have a testing class (named classTestingC.ctl)


#uses "Globals/GlobalControl.ctl"

class cclass
{
public cclass()
{
DebugN("Initialize c Class");
DebugN("CC-Init: " + doorStatusList);
}

public dyn_string returnList()
{
DebugN("CC-PostInit: " + doorStatusList);
}
};

--------------------------

This is in the scopelib of a blank panel that has an initialize function that calls initializeObject();

#uses "Devices/classTestingC.ctl"

cclass thisCClass = cclass();

void initializeObject() {
//cclass thisCClass = cclass();
DebugN("Direct: " + doorStatusList);
thisCClass.returnList();;

}

-------------------------------------

Here is the log file output:

WCCOAui1:["Initialize c Class"]
WCCOAui1:["CC-Init: 0"]
WCCOAui1:["Direct: Emergency Mode | Estop | Error | Undefined | Stopped | Stopping | Opening | Closing | Open | Closed"]
WCCOAui1:["CC-PostInit: Emergency Mode | Estop | Error | Undefined | Stopped | Stopping | Opening | Closing | Open | Closed"]


So, what I'm seeing is that the class does not get access to the contents of the ctl file included by #uses. I have confirmed this in both 3.15 and 3.16.

Am I doing something wrong and/or dumb?

leonmf
Posts:6
Joined: Mon Aug 11, 2014 6:21 pm

Re: OOP Access to #uses in class initialize doesn\'t work - should it?

Post by leonmf »

I should note that I can solve this problem by doing this:

cclass thisCClass;

void initializeObject() {
thisCClass = newcclass();
DebugN("Direct: " + doorStatusList);
thisCClass.returnList();;

}

baumanndo
Posts:10
Joined: Tue Dec 14, 2010 8:03 am

Re: OOP Access to #uses in class initialize doesn\'t work - should it?

Post by baumanndo »

I can reproduce your problem in 3.15.

A.ctl:

Code: Select all

public dyn_string ds = makeDynString("asdf");

class A
{
  public A()
  {
    DebugN("A::A()");
  }

  public void sayHello()
  {
    DebugN("hello from A");
  }
};

public A a = A();
B.ctl

Code: Select all

#uses "A.ctl"

class B
{
  public B()
  {
    DebugN("B::B()");
  }
};

public B b = B();
Test.ctl

Code: Select all

#uses "B.ctl"

class C
{
  public C()
  {
    DebugN("C::C()");
    // DebugN(ds); -> gives "Variable not defined" 
    // a.sayHello(); -> gives "Unexpected state, Test.ctl    Line: 9, can't execute"
  }
};

public C c = C();

int main()
{
  DebugN("MAIN");
  return 0;
}
Executing Test.ctl gives:
WCCOActrl1:["C::C()"]
WCCOActrl1:["A::A()"]
WCCOActrl1:["B::B()"]
WCCOActrl1:["MAIN"]
It seems that the initialization order of global variables, imported from libraries into script or panel files, is incorrect.
The global variable "c" in Test.ctl is initialized before the imported variables "a", "b" and "ds".
Using "a", "b" or "ds" in the constructor of class "C" results in an error when initializing variable "c".

Does your log output also contain a "Variable not defined" error a few lines after "WCCOAui1:["CC-Init: 0"]"?

leonmf
Posts:6
Joined: Mon Aug 11, 2014 6:21 pm

Re: OOP Access to #uses in class initialize doesn\'t work - should it?

Post by leonmf »

I don't recall if there was a variable not defined error as I was able to work around the issue and I've deleted the test code.

Would you like me to regenerate and test?

baumanndo
Posts:10
Joined: Tue Dec 14, 2010 8:03 am

Re: OOP Access to #uses in class initialize doesn\'t work - should it?

Post by baumanndo »

Leon Grossman wrote:
Would you like me to regenerate and test?
Ok. No need to regenerate it. ;)

It did some further experiments.
Making the global variables "a" and "b" constant affects the order of initialization. Now the ordering is as expected:
WCCOActrl1:["A::A()"]
WCCOActrl1:["B::B()"]
WCCOActrl1:["C::C()"]
WCCOActrl1:["MAIN"]
Also interesting to note: Changing the constness of the global variable "c" has no effect in this case.

baumanndo
Posts:10
Joined: Tue Dec 14, 2010 8:03 am

Re: OOP Access to #uses in class initialize doesn\'t work - should it?

Post by baumanndo »

Another interesting effect of this problem:

A.ctl:

Code: Select all

class A
{
  public A()
  {
    DebugN("A::A()");
    c.sayHello(); //

mkoller
Posts:741
Joined: Fri Sep 17, 2010 9:03 am

Re: OOP Access to #uses in class initialize doesn\'t work - should it?

Post by mkoller »

Main question: what do you expect the "dyn_string doorStatusList" to be ?
It's NOT a manager global variable!
Note that you must use the global keyword in a script library to make a global variable a manager global one.
All other (non-global, non-const) vars in any script library end up as own instances(!) in every script which is executed (but not in scope libraries!).

So what you see is expected. The scope lib initializes a class instance. The scopeLib does not get a copy of the doorStatusList variable, therefore the constructor of the class does not see it.
You should also see an error like:

WCCOAui (0), 2018.05.11 23:15:05.194, CTRL, SEVERE, 73, Variable not defined,
Module: _QuickTest_
Panel: /home/projekte/orig315/panels/newPanel.pnl [newPanel.pnl]
Script: ScopeLib
Library: /home/projekte/orig315/scripts/libs/classTestingC.ctl
Line: 8, doorStatusList

When you then call the initializeObject() function from any other script, that script WILL get its own instance of the doorStatusList variable, and therefore you
can use it.

But I'm pretty sure what you really want here is either a
const dyn_string doorStatusList
or a
global dyn_string doorStatusList

both will be created only ONCE and are manager global, therefore available even in the scope lib class instances

leonmf
Posts:6
Joined: Mon Aug 11, 2014 6:21 pm

Re: OOP Access to #uses in class initialize doesn\'t work - should it?

Post by leonmf »

Simple mistake on my part, then. I will implement this change and test.

Thank you!

8 posts • Page 1 of 1