LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Dr. Damien's Development - Running Top Level VIs II - SubPanel Use

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:

  • I love the LaunchFunctionVI icon.  Very descriptive.
  • 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.
  • 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.
  • 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?
  • Your Function vis have a hidden backwards error wire from the Clear Error output back to the input shift register.  🙂

 

Plus.lvlib_PlugIn_Plus.lvclass_Function_BD.png

 

 

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.)

0 Kudos
Message 21 of 35
(2,487 Views)

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.

Message Edited by jmcbee on 03-29-2010 04:08 PM
Message Edited by jmcbee on 03-29-2010 04:09 PM
0 Kudos
Message 22 of 35
(2,483 Views)

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.


Now, if you really want to mess around you can use the the property Control Value set and/or control ref[] from the sub panels to push values and captions and stuff into them. 😄

/Y
Message Edited by Yamaeda on 03-30-2010 12:13 AM
G# - Award winning reference based OOP for LV, for free! - Qestit VIPM GitHub

Qestit Systems
Certified-LabVIEW-Developer
0 Kudos
Message 23 of 35
(2,480 Views)

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.

0 Kudos
Message 24 of 35
(2,447 Views)

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 Smiley Very Happy  I really should run VI Analyzer on these things before I post them.

 

Thanks for your comments!  Keep them coming.

0 Kudos
Message 25 of 35
(2,439 Views)

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.

0 Kudos
Message 26 of 35
(2,433 Views)

(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.

0 Kudos
Message 27 of 35
(2,428 Views)

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.

 

 

0 Kudos
Message 28 of 35
(2,382 Views)

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.

Message 29 of 35
(2,354 Views)

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:

  • Understanding the mechanics of OOP (inheritance, dynamic dispatch, etc.) is not the same as knowing how to design an OO system.  The mechanics can be picked up quite quickly.  Learning to create good designs takes much longer.  If you don't have an experienced OO designer nearby it will take longer as you have to learn by trial and error.  I strongly recommend picking up Head First Design Patterns.  It is an excellent introduction into OO design patterns.  The code examples are in Java, but I found the book very approachable and readable.  The GoF Design Patterns is an excellent reference and provides more details on when to apply specific patterns and the tradeoffs associated with them.  The code examples are less useful for me; if I recall correctly they are mainly in c++ but there may be some smalltalk in there too.  Still, the text is very informative.  It was my second purchase.
  • OO programs tend to have many small vis as opposed to fewer large vis.  Structured programmers often look at them and cry "code bloat!"  Smile, nod, and be comforted that three months down the road you will be able to make a quick change confident that you haven't accidentally broken the app somewhere else, while they spend days tracing through their code trying to fix new problems the change created.
  • Be prepared for longer load times, especially in large applications.  When a LV class is loaded it loads all the classes member vis.  If your app is completely OO, that means everything gets loaded.  When you combine that behavior with more vis, the result is that you have time to visit the forums while waiting for your app to load.  (That's been my experience at least.)  We have a large app that takes 5-8 minutes to load in LV8.6.
  • I find the promise of code reuse applies more to reusing code between projects rather than reusing code within a project.  In fact, an OO project will have more code than an equivalent structured programming project.  (I consider that the cost of creating modular programs.)  As your reuse library grows you will end up needing less application specific code to complete a project.
  • Avoid the temptation to create a large inheritance hierarchy--it likely won't work in the long run.  Inheritance is arguably the most well-known feature of OOP, so when people cut their teeth on OO design they usually overuse inheritance.  Don't get me wrong, inheritance is an important part of OOP, but it also is somewhat restrictive.  In general you will get much more flexibility using object composition.

 

So jump aboard, drink the kool-aid, and enjoy the process of learning a new programming paradigm.

Message 30 of 35
(2,327 Views)