11-19-2012 05:43 PM
Hi guys,
We have some software that controls different kinds of "widgets." They are identicle in function, but they are from differering vendors and have different drivers and APIs. But here's the tricky part: they may be used by themselves, or in any combination you can think of, up to 3 at a time.
Currently, we use a seperate version of our software for each widget combination, duplicating a massive amount of code- since the only thing we do with each widget is configure it, then read its data (which it continuously takes), then close it when the program is closed. The rest of the software is the same.
I'm wondering what the best approach would be to combine the code. I'm thinking LabVIEW Classes would be a good approach, but, I am new to OOP so I'd like some advice with the design. I've seen the example "Board Testing", that looks interesting and somewhat similar - there they use a different subclass for each board. Analogously I guess I would use a different subclass for each widget. But I'm not sure this is a good idea, since I can have various combinations of the widgets. My main class wire would then have to contain multiple sub-classes.
Any ideas?
11-19-2012 08:33 PM
Your widgets would all be "siblings" in that case so you can do things like bundle whichever combination you want into an array and run them through a dynamic dispatch method. Sounds like you might want to start off by reading up on OOP. I would suggest the book/ebook: "The Object Oriented Thought Process" by Matt Weisfield.
11-21-2012 02:43 PM - edited 11-21-2012 02:44 PM
Thanks, that's what I'm doing; using a Widget maser class from which I have inheriting child classes for the specific widgets.
I have a question: Each widget needs a refnum to the device driver - but if, say, I have 2 widget A's, then they need to share that refnum.
Right now, I am creating one class for each widget, with the refnum in the classes' private data. How can I share that refnum between classes of identicle widgets?
Would I just create another class, maybe Widget Refnums, as friend class? And I could fill it using First Call? function of each sibling class' initialization method. That's what I'm thinking, but not sure if there's a better way.
11-21-2012 03:48 PM - edited 11-21-2012 03:49 PM
Maybe a little simplified picture.
I have Widget A1 connected, of Widget type A. I create an instance of WidgetA class, then open a reference to its driver
I connect WidgetA2, also of Widget type A; I make a new instance of the WidgetA Class. But I need to use the same reference.
What's the most efficient way of sharing this data? Googling around I found this on MSDN:
Each class instance maintains its own data. The data is isolated in such a way that if a data member changes in one instance of the class, the same data member in another instance of the class is unaffected. However, the static members of a class provide a way for all instances of the class to use the same memory location or function.
If you prefix one of your data members with the static keyword, Visual C# .NET or Visual C# 2005 creates a single location for that static data member. The data member is exposed to each instance of the class that references the storage location. If you change the value of the shared data member in one class instance, it is changed in all the other instances.
That's precisely what I need it seems. How do I implement this in LVOOP?
11-21-2012 03:54 PM
I guess I could just use a global variable...but that seems inelegant.
11-21-2012 04:02 PM
What about defining a method called "Initialize" in your parent class that requires your child classes to override. Each child class then calls it's own "Initialize" method for the particular hardware it is expected to control and keeps the reference in it's own private data. This assumes one child class dedicated to a particular kind of device. I wasn't sure why you would want multiple classes accessing the same device when you could build all the functionality into one object.
11-21-2012 04:03 PM
@pobrepablo1 wrote:
I guess I could just use a global variable...but that seems inelegant.
No, don't do that. I would recommend that you store the reference in your private data and that the reference is set via a method or as an input to your create method. Alternatively you could use a DVR inside the child class (for this particular widget) and the first instance of this class would initialize it. Following instances would simply read the reference.
11-21-2012 04:59 PM - edited 11-21-2012 05:00 PM
OK, with these comments in mind I've created an Initialize method. "Wrapper" is the name of the driver refnum.
I'm calling this subvi with "initialize" as the argument iff First Call? is true. I think this is the best approach? Or at least simplest for me. I've never used DVRs before (except on a TV... ;))
11-21-2012 05:06 PM
@pobrepablo1 wrote:
OK, with these comments in mind I've created an Initialize method. "Wrapper" is the name of the driver refnum.
I'm calling this subvi with "initialize" as the argument iff First Call? is true. I think this is the best approach? Or at least simplest for me. I've never used DVRs before (except on a TV... ;))
This would not be the way that I would implement this. First of all I would have explicit methods for my operations instead of implementing like the old style action engine. Also, I would store the data in the class private data, not in unitialized shift registers. I would consider using a better name than "Wrapper". It is a poor name for your data.
11-21-2012 05:13 PM - edited 11-21-2012 05:13 PM
I have no choice in the name "wrapper." makes no sense, I know, but that's the refnum name that the driver vendor chose, and I want to maintain consistency with their API, which we're already familiar with.
Also, that data is in the private data of each class - hence the bundle action - isn't it? But I have to get it there somehow, hence the AE. This function is only called once for each class initialization.