03-29-2010 05:04 PM
Just to satisfy my own curiousity I modified your code and made each of the Function vis dynamic dispatch members of their respective classes. The class input and output are simply wired through. It works the same as it did when the Function vis were not part of the classes. Perhaps it is earlier versions that don't have this functionality rather than later versions?
I know you didn't ask for feedback, so feel free to ignore me, flame me, or throw darts at a printout of my avatar for any of these comments:
jmcbee
Do you have a link to the LAVA example you mentioned?
Yep, it's in the Code Resository here. It's labelled a framework but you can't simply drop it in your project and start building on it. You'll have to clean out his example code first. Still, it's a very good implementation. (Note that it's an Active Object example and has nothing to do with subpanels.)
03-29-2010 05:08 PM - edited 03-29-2010 05:09 PM
Do you have a link to the LAVA example you mentioned?
Yep, it's in the Code Resository here. It's labelled a framework but you can't simply drop it in your project and start building on it. You'll have to clean out his example code first. Still, it's a very good implementation. (Note that it's an Active Object example and has nothing to do with subpanels.)
Gotcha, I just want to take a look at it and hopefully learn something new.
03-29-2010 05:10 PM - edited 03-29-2010 05:13 PM
Thanks for a great example, i enjoyed studying it. It's basically a queue driven state machine, with 1 state being event handling. I think a more common approach would be to have the event in a loop of it's own, but i liked it.
03-31-2010 07:39 AM
In LabVIEW 8.2, all VIs of an object were reserved (put into a "running" state) when any VIs of the object were part of actively running code. This prevents them from being opened and Run using VI server, because they are already "running". I wrote the example in LabVIEW 8.2. In LabVIEW 8.5, this was fixed so that only those VIs actually used are reserved, allowing VIs to be opened and Run from inside an object. This should be the case going forward, so the architecture can be cleaned up quite a bit by porting forward one version of LabVIEW.
However, you cannot dynamically dispatch a VI by setting the front panel control after opening it. It won't error, but you will always get the VI you actually opened, not a dynamically dispatched one. This is not a problem in this use case, since the dynamic dispatch occurs in the code which opens the plug-in, not the plug-in itself.
03-31-2010 08:00 AM
Actually, I encourage feedback, suggestions, and commentary on anything I post in Dr. Damien's Development. I would like to learn as much from you as you learn from me (and probably have).
I love the LaunchFunctionVI icon. Very descriptive.
I enjoy making icons. I usually use Google to find images and GIMP to edit them. In this case, I found a nice rocket launch image, pasted one of the standard VI icons on top of it, then converted the whole thing to 256 colors using Floyd-Steinberg dithering.
Putting the RunVI invoke node in PlugInParent:GetFunctionReference threw me for a bit of a loop. I intuitively expected it to be in the Launch vi and running across it there had me confused for a bit. Any vi with "Get" or "Set" in the name I associate with accessing data.
Actually, PlugInParent:GetFunctionReference does access data most of the time it is used - it returns the function reference. It is also overloaded to launch the function, if needed. I like accessors which give pure functionality that the user does not have to think about. This accessor will always return the function reference, regardless of history. It makes it easy to use and safer to develop with. It does require more care in creating the object.
I like the way you handle the control references in LaunchFunctionVI to make sure the events are set before changing the data. Adding the class controls on the Function front panels was painless.
That code is actually a bit on the inefficient side, since it uses array builders in a loop. But it makes a good example. I would probably clean it up a bit before I used it with a complex front panel.
The GetFunctionReference methods for your child classes contain the exact same code (except for the PlugIn object) whose sole purpose is to get the path to the correct directory. The Get LV Class Path primitive would be a lot simpler here--I presume that's not available in the version you used for this project?
You are correct. The Get LV Class Path primitive did not exist in LabVIEW 8.2.
Your Function vis have a hidden backwards error wire from the Clear Error output back to the input shift register. 🙂
Oops I really should run VI Analyzer on these things before I post them.
Thanks for your comments! Keep them coming.
03-31-2010 08:50 AM
DFGray wrote:Actually, PlugInParent:GetFunctionReference does access data most of the time it is used - it returns the function reference. It is also overloaded to launch the function, if needed.
This is the part that confused me. There is a "GetFunctionReference" vi that does more than just returns a reference to the Function.vi (by launching it first) and a "LaunchFunctionVI" vi that doesn't launch the Function vi. I'm not saying you coded it up wrong, just that the names you used don't quite reflect what the vis actually do.
During my dev process I often find that a vi no longer does what I originally intended and needs to be renamed. I remember having a lot of issues with renaming vis in 8.2, so I certainly don't blame you for not going there. Thankfully the more recent versions handle moving/renaming much better.
03-31-2010 09:10 AM
(Grr... this board times out too quickly.)
DFGray wrote:
That code is actually a bit on the inefficient side, since it uses array builders in a loop.
Meh... first make the code work, then make it fast. The quest for perfect efficiency is usually a time sink that produces little (if any) practical value. The overhead in dev time and code complexity to implement a buffered array isn't worth it in this case.
04-05-2010 08:35 PM
Damien,
I am currently building an app which will use subpanels.
http://forums.ni.com/ni/board/message?board.id=170&thread.id=487756&view=by_date_ascending&page=1
I was very excited when I came across this thread. However, your implementation assumes knowledge about object-orientated programming, does it not?
I am rather confused now as to whether I should follow the same architecture as you have used in your example. I am quite experienced with LV but have no idea about LV classes and OOP.
What do you suggest?
Thanks,
Battler.
04-06-2010 08:12 AM
In my example, objects are used to provide an easy mechanism for switching between plug-ins (dynamic dispatch is a wonderful thing). You can use libraries in almost the same fashion, since libraries also provide namespacing. It will require more code, since you have to manage the switching yourself. Thus, I would encourage you to learn object-oriented programming. It requires a major change in how you think about program design, but the end result is well worth the pain. Large programs, especially those like you describe in your post, are much easier (and faster) to write, test, and maintain if written in a modular, object-oriented manner. I learned object-oriented programming using C++ after being a C user for ten years. It took about a month of use (I was creating a large program at the time) before the concepts really sank in. Now I don't wish to program any other way, and haven't, even if the underlying language (pre 8.2 LabVIEW) did not natively support object-oriented programming.
Work through the LabVIEW examples on LabVOOP and post any questions you may have. Better yet, you could keep a running "blog" on these discussion forums of your experience. It would help others in your position and we could improve our documentation and code, given your pain points. This assumes you can post your code.
Good luck. Let us know if you run into issues.
04-07-2010 09:38 AM
battler. wrote:I am quite experienced with LV but have no idea about LV classes and OOP.
I'll second Damien's suggestion to learn OOP. I started using LVOOP about 2 years ago and haven't looked back. Very few people who take the time to learn OOP go back to to the structured programming (data and procedures--or "traditional" LV programming) regardless of the language used.
There are, however, a few caveats:
So jump aboard, drink the kool-aid, and enjoy the process of learning a new programming paradigm.