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?
OOP Access to #uses in class initialize doesn\'t work - should it?
- leonmf
- Posts:6
- Joined: Mon Aug 11, 2014 6:21 pm
OOP Access to #uses in class initialize doesn\'t work - should it?
- leonmf
- Posts:6
- Joined: Mon Aug 11, 2014 6:21 pm
Re: OOP Access to #uses in class initialize doesn\'t work - should it?
I should note that I can solve this problem by doing this:
cclass thisCClass;
void initializeObject() {
thisCClass = newcclass();
DebugN("Direct: " + doorStatusList);
thisCClass.returnList();;
}
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?
I can reproduce your problem in 3.15.
A.ctl:
B.ctl
Test.ctl
Executing Test.ctl gives:
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"]"?
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();
Code: Select all
#uses "A.ctl"
class B
{
public B()
{
DebugN("B::B()");
}
};
public B b = B();
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;
}
It seems that the initialization order of global variables, imported from libraries into script or panel files, is incorrect.WCCOActrl1:["C::C()"]
WCCOActrl1:["A::A()"]
WCCOActrl1:["B::B()"]
WCCOActrl1:["MAIN"]
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?
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?
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?
Leon Grossman wrote:

It did some further experiments.
Making the global variables "a" and "b" constant affects the order of initialization. Now the ordering is as expected:
Ok. No need to regenerate it.Would you like me to regenerate and test?
It did some further experiments.
Making the global variables "a" and "b" constant affects the order of initialization. Now the ordering is as expected:
Also interesting to note: Changing the constness of the global variable "c" has no effect in this case.WCCOActrl1:["A::A()"]
WCCOActrl1:["B::B()"]
WCCOActrl1:["C::C()"]
WCCOActrl1:["MAIN"]
- baumanndo
- Posts:10
- Joined: Tue Dec 14, 2010 8:03 am
Re: OOP Access to #uses in class initialize doesn\'t work - should it?
Another interesting effect of this problem:
A.ctl:
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?
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
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?
Simple mistake on my part, then. I will implement this change and test.
Thank you!
Thank you!