1. Benefits of Using LabVIEW Object-Oriented Programming
1. What is object-oriented programming (OOP) in general and why use it?
Object-oriented programming has demonstrated its superiority over procedural programming as an architecture choice in several programming languages. It encourages cleaner interfaces between sections of the code, it is easier to debug, and it scales better for large programming teams.
The idea behind object-oriented programming is that a computer program may be seen as comprising a collection of individual units, or objects, that act on each other, as opposed to a traditional view in which a program may be seen as a collection of functions, or simply as a list of instructions to the computer. Each object is capable of receiving messages, processing data, and sending messages to other objects. Each object can be viewed as an independent little machine or actor with a distinct role or responsibility.
Object-oriented programming is claimed to promote greater flexibility and maintainability in programming, and is widely popular in large-scale software engineering. Furthermore, proponents of OOP claim that OOP is easier to learn for those new to computer programming than previous approaches, and that the OOP approach is often simpler to develop and to maintain, lending itself to more direct analysis, coding, and understanding of complex situations and procedures than other programming methods.
2. What are the differences between OOP in C++ and LabVIEW?
C++ is a text-based, functional language. LabVIEW is a graphical, dataflow language. The different paradigms require differences in how they present OO features:
- LabVIEW has an ultimate ancestor class for all objects. C++ does not.
- C++ has constructors. LabVIEW has no need for them.
- C++ has destructors. LabVIEW has no need for them.
- C++ has both a reference and value syntax for passing objects as parameters. LabVIEW has a value syntax only, with references created through other features.
- LabVIEW has automatic data mutation so the user can retrieve old data even if the class has been edited. C++ does not, requiring the user to track version changes and write mutation code for data.
- C++ has templates. LabVIEW 8.2 and later does not.
- C++ has pure virtual functions. LabVIEW 8.2 and later does not.
- C++ has multiple inheritance. LabVIEW does not.
For more explanation of these difference, please refer to the white paper, LabVIEW Object-Oriented Programming: the Decisions Behind the Design.
3. What are the primary benefits of LabVIEW object-oriented programming?
A. What is the benefit to a brand new user of LabVIEW?
1. The strength of LabVIEW is that it makes the power of computer science accessible to non-programmers. LabVIEW object-oriented programming brings some of the most advanced programming techniques into the grasp of beginning users. OO requires more of a commitment to planning, and so is generally chosen only if the user is embarking on a large software effort.
2. OO provides a way of planning software using terms that match a feature specification. The description of the feature discusses about items that appear on the screen, or pieces of data that the feature will manipulate. With OO, you can write code that plans itself around those same terms: database objects, button objects, e-mail objects.
B. What is the benefit to an experienced G programmer who does not practice OOP?
1. Easier to debug—More modular code allows you to narrow the list of VIs where a bug might be.
2. Easier maintenance—OO design leads to more structure, which helps developers to be more productive over time. Developers can easily identify areas where they want to add features, and are less likely to introduce errors into unrelated sections of code.
4. Who should use LabVIEW object-oriented programming?
- VIs to be maintained for a long time
- Large application
- Multiple developers working on same VIs
5. Who should not use LabVIEW object-oriented programming?
- Express users
- For the quick, single VI to take a measurement, LabVIEW classes are overkill
6. What are some examples of how/where a customer would use LabVIEW object-oriented programming?
For a test and measurement example that contrasts a task-based approach and an object-oriented approach, refer to the Board Testing example that ships with LabVIEW 8.2 and later.
2. How to Use LabVIEW Object-Oriented Programming
1. Where can I learn more about using LabVIEW object-oriented programming? For example are there training material, app notes, tutorials, demo scripts, and examples?
LabVIEW 8.2 and later ships with several LabVIEW object-oriented programming examples. Refer also to the Additional Resources section of this document.
2. How do I transition to using LabVIEW object-oriented programming on my existing projects?
The simplest start is to convert existing type definitions to LabVIEW classes. You can do this by right-clicking a typedef in the Project Explorer window and selecting Convert Contents to Class from the shortcut menu. See the LabVIEW Help for more information about creating LabVIEW classes.
Note: LabVIEW does not preserve the default value of controls and constants during the conversion process. To access the details of the typedefs, add VIs to those classes that need to access to the type definition. This grouping of VIs based on the data they act on is fundamental to object-oriented programming. Refer to the two NI Week 2006 presentations listed below in the Additional Resources section for more information about object-oriented design.
3. How do I implement a "by reference" implementation in LabVIEW object-oriented programming?
Refer to the Reference Object example that ships with LabVIEW 8.2 and later.
Essentially, you make the private data of a class be a reference. The example shows how to use a single-element queue reference for this purpose. You may also use the GOOP Toolkit (refer to the LabVIEW Object-Oriented Programming & GOOP Toolkit section below).
4. Do LabVIEW classes work with LabVIEW Real-Time or any non-desktop target?
With LabVIEW 2009, object orientation is now supported on LabVIEW real-time targets. Object-oriented programming is not supported in real-time with LabVIEW 8.6 and prior.
5. When closing a VI, why does LabVIEW sometimes open two Save Changes dialog boxes; one for the VI and subVIs and one for LabVIEW classes? Why not open one dialog box that saves everything?
When you close a VI, LabVIEW knows all the subVIs that will be unused as a result of closing that VI, so LabVIEW can ask to save them all at once. Classes, however, cannot leave memory until all data instances have left memory, and LabVIEW cannot know whether closing any given VI will actually close out the last instance of data. A VI might not have any reference to the class in its code, but it might still have an instance of the class stored in a variant somewhere. If all VIs were idle, LabVIEW could determine how many instances of the class will leave with this set of VIs and see if that accounts for all the instances of the class remaining in memory. Then LabVIEW would know that the class is leaving memory with the VIs and could ask about the class in the same Save Changes dialog box as the other VIs/libraries. But if any VI is still running, the number of instances can be constantly fluctuating. And while VIs are running, data can be hiding in impossible-to-search locations, such as a queue or notifier, and these extra spaces only get disposed when the VI goes idle. A running VI also can create new instances in locations that LabVIEW already checked. So it is impossible to count instances while the VIs are running. Since LabVIEW does not abort running VIs until after asking whether or not to save the changes, LabVIEW cannot yet know if the class will be leaving memory. Even if all the VIs were idle and LabVIEW could do the search for data, that search would be extremely slow, so LabVIEW does not attempt it at all. Thus, when you close a VI, the classes frequently end up getting their own Save Changes dialog box.
The only time LabVIEW can fold classes in with everything else and offer a single Save Changes dialog box is when you are closing the project. In that case, because every VI in the project will be closed down, LabVIEW know that means all the data instances of the class will be disposed without having to account for them all.
3. LabVIEW Object-Oriented Programming & GOOP Toolkit
1. What is the GOOP Toolkit?
You can find a free download of the GOOP Toolkit 1.0 on the National Instruments website. You can purchase later versions of the toolkit from Endevo.
2. Can I continue using GOOP in LabVIEW 8.2 and later?
3. How can GOOP and LabVIEW object-oriented programming work together? How and when should you use the Endevo GOOP Toolkit in conjunction with or instead of LabVIEW object-oriented programming?
Most users will find the LabVIEW classes work best for their applications. LabVIEW classes behave just like the clusters that users are familiar with.
You can use references to handle communication between sections of code that execute in parallel. For customers who are actually modeling system resources, the reference model becomes very useful and they may wish to create GOOP classes. References are also valuable when creating graph and tree data structures. Even in these cases, the data fields at the core of the GOOP class may well be LabVIEW classes. However, when using references or any other means of communicating between sections of parallel code, you need to know about locking, race conditions, and other complexities that arise.
You can use the reference model to guarantee that you never duplicate that class in memory. For a class that requires a lot of memory, this can be an advantage.
4. Should I transition my application that uses the GOOP Toolkit to LabVIEW object-oriented programming? What existing customer applications using Endevo's GOOP Toolkit would make sense implement in LabVIEW object-oriented programming?
There is no requirement that you rewrite existing GOOP classes as LabVIEW classes. One reason is that you should never destroy working code without a compelling reason, and the GOOP classes will continue to work in LabVIEW 8.2 and beyond. After all, the GOOP Toolkit is written in LabVIEW. Further, changing code that works by-reference into code that works by-value is a significant undertaking.
One reason to transition is performance. A lot of overhead is generated for an object when every function call has to look up the reference, lock the instance, and extract the data. The GOOP Toolkit does an amazing job of minimizing this overhead, but it is there nonetheless. Further, operating using a refnum prevents many operations that could otherwise proceed in parallel. If you have a class that does not need the by-reference behavior and does need better performance, then you could consider transitioning the GOOP class to the LabVIEW class.
5. How do I transition my application that uses GOOP to LabVIEW object-oriented programming?
This is a question that must be answered on a case-by-case basis. LabVIEW has no automated way to make the conversion.
6. What is the performance of LabVIEW object-oriented programming vs. the Endevo GOOP Toolkit?
Because of the consistency with dataflow and the native compiler implementation of dynamic dispatching, LabVIEW classes will tend to outperform GOOP classes in equivalent situations. That having been said, there are very few equivalent situations. The LabVIEW classes are designed to replace clusters and to enhance dataflow. GOOP classes are a way to add references to LabVIEW. They serve two different purposes in the language. When creating new classes, you should make the decision between a GOOP class or a LabVIEW class based on the functionality the class needs, not based on performance predictions.
4. Technical Details
1. What is the performance impact of using a LabVIEW class versus a cluster typedef?
Benchmarking on a range of computers shows the performance between these two is nearly identical. Refer to the question below for more performance information.
2. What is the performance overhead of a dynamic subVI call (vs. a normal subVI call)?
A dynamic dispatching subVI has some small overhead when LabVIEW looks up which subVI to invoke. The overhead is constant. It does not increase as you add more classes or as you add more dynamic VIs to a class. There can be a performance hit if the subVI call has to make extra copies of the parameters to match the functionality of the actual subVI LabVIEW invokes. You can avoid this by wiring the input front panel terminals to output front panel terminals even on dynamic VIs that you never expect to call (for example, parent VIs that exist only to define the connector pane for children to override). Refer to the white paper LabVIEW Object-Oriented Programming: the Decisions Behind the Design for details on how the dynamic dispatching is able to achieve constant overhead performance.
3. How do LabVIEW class libraries differ from project libraries?
A LabVIEW class is a type of project library. It is a project library dedicated to the task of defining a data type. Like a project library, the LabVIEW class defines scope and namespace for its member VIs, and a VI can be owned by one and only one LabVIEW class.
The LabVIEW class has a private data control. This is a control VI that defines the data values of the class. This special control is not part of other library types, and is actually saved inside the class file. LabVIEW classes have all the properties that libraries have, and some additional properties. You can see the additional properties in the Class Properties dialog box on the Inheritance, Probes and Wire Appearance pages.
The only ability that project libraries have that LabVIEW classes do not is the ability to contain sublibraries.
4. When using LabVIEW object-oriented programming, what gets loaded and when?
If a VI uses a LabVIEW class, then loading the VI loads the class, just like a VI loads all of its subVIs. A LabVIEW class in turn loads all of its member VIs and its parent class. Parent classes do not automatically trigger the loading of their child classes. Parents do not have any links to children. A member VI of a parent may use a child class and thus LabVIEW loads the child class.
5. What does "by-value" and "by-reference mean?" What are the pros and cons of each?
"By-value" means that the wire carries actual data of the type of the wire. "By-reference" means that the wire carries a reference to the data of the type, and LabVIEW stores the actual data in some central repository. Most data types in LabVIEW, including numerics, arrays, clusters, strings, Booleans, and paths are by value. Typically, the only types that are by reference are those that use communications or reflect system resources, such as file refnums, queue refnums, and VI Server refnums. LabVIEW classes are by value. In by-value syntax, each object has its own data values, which you can modify independently of other objects. In by-reference syntax, there is a single instance of data to which multiple objects refer. If one object modifies the data, it has to be careful not to conflict with other objects who are reading and writing that data. The primary pros and cons are:
- By-value is better in a highly parallel environment such as LabVIEW because it avoids race conditions.
- By-value allows the compiler to determine when copies of data need to be made, lessening the burden on the programmer.
- By-reference gives the programmer responsibility for allocation, which is sometimes a better model for single-instance resources and large data sets.
6. Why is LabVIEW object-oriented programming "by value?"
Refer to the white paper LabVIEW Object-Oriented Programming: the Decisions Behind the Design.
7. Does National Instruments have UML tools for creating/managing LabVIEW classes?
NI does not have a native UML tool. Endevo makes a tool for generating classes from UML diagrams, and generating UML diagrams from code. The tool currently works for GOOP classes (refer to the LabVIEW Object-Oriented & GOOP Toolkit section above), but an upcoming release will support LabVIEW classes as well.
8. Why can't I use "Make Current Value Default" on LabVIEW class controls and indicators? Why can't I set the values of LabVIEW object-oriented programming constants?
Make Current Value Default is a valuable feature of LabVIEW. You might use it frequently for building test VIs. This feature is not supported for LabVIEW classes in LabVIEW 8.2 and later because of the complexity of providing a good user interface so that the user knows when the data is something other than the default-default, even though the user cannot actually see the data because the data is private. This feature is a high priority to be included in a future LabVIEW version.
9. Why can't I make a dynamic VI reentrant?
Reentrant dynamic VIs are not supported feature in LabVIEW 8.2. Because dynamic subVI nodes at edit time do not know which subVI LabVIEW will actually invoke at run time, each node would have to create clones of all the possible subVIs. This turns out to be prohibitively expensive in memory.
(LabVIEW 8.5) You can use reentrant dynamic VIs in LabVIEW 8.5.
You can configure a dynamic dispatch VI to be recursive, or to use itself as part of its own definition. Recursive VIs can call themselves on their own block diagram, including the block diagram of subVIs. Recursion is useful if you want to operate many times on the output of the same process. You can configure a dynamic dispatch member VI to allow recursion by setting it to be reentrant and to share clones between instances.
Complete the following steps to configure a VI for recursion.
Open or create a dynamic dispatch member VI.
Make the VI reentrant.
Select File»VI Properties to display the VI Properties dialog box.
Select Execution from the Category pull-down menu to display the Execution Properties page.
Place a checkmark in the Reentrant execution checkbox and select Share clones between instances.
Develop the member VI to complete a recursive operation.
Note- Not accounting for infinite recursion causes unnecessary memory usage and might crash LabVIEW. To avoid infinite recursion, consider calling the recursive VI in a Case structure.
5. Additional Resources
1. LabVIEW Object-Oriented Programming: the Decisions Behind the Design. White paper.
2. Community web document: Moving Common OO Design Patterns From Other Languages Into LabVIEW
This document describes various design patterns from other programming languages and how to implement those patterns in LabVIEW. The patterns can help you identify which classes you need to create to solve a particular programming problem and make the interactions among those classes most efficient. This document is intended to change over time as improved programming techniques are identified.
3. One-hour video presentation on getting started with LVOOP: Object Oriented Programming in LabVIEW
This video is a one-hour presentation by Trevor Christman about the basics of object oriented programming and how those basics can be accessed in LabVIEW. A great resource for those who prefer video to text learning.
4. Hardware abstraction with LV Classes: How to Mitigate Hardware Obsolescence in Next-Generation Test Systems (white paper) - Mitigating Obsolescence with Hardware Abstraction Layers (webcast)
5. Object Oriented Design Patterns Technical Manual and Exercises - This is the documentation and support VIs for a self-paced hands-on walkthrough of some intermediate level design patterns with LabVIEW classes. It is intended for a student who has the grasp of the basics of LabVIEW classes and wants to see how to use those classes in a larger application context. This hands-on session was first presented at NI Week 2011. The VIs on the site are saved for LV version 2011; VIs for version 2010 are available -- search in the web page comments section for "2010".