The LabVIEW Container is a new way to pass data around on your block diagram. It combines the strengths of the array with the strengths of the cluster. NOTE: this is an early release! Containers are still in development.
Let me first start off by giving some motivation. I created the Container to combine the strengths of the array and cluster.
The LabVIEW Container
In summary, the LabVIEW container allows you to store named data of ANY type in hierarchical relationships. The strength of the Container is its flexibility at run time. You can change the hierarchy or change what data you're accessing programmatically, almost as if you could programmatically edit or interact with a cluster. The API below describes how you interact with Containers.
Introduction to the Container API
I've created an API so that you can easily and intuitively construct, compose, access, display and clean up your containers. Below is a brief example of the most basic usage of the API:
The first step is to bring a Container into existence and give it a name with the Create.vi. Think of this as dropping an empty cluster constant on the block diagram.
To create a hierarchy, use the "Add Child to Container.vi". This is similar to adding a cluster to a cluster, or (if it were possible) putting an array into an array.
The Get \ Set Attribute VIs are designed to allow adding or retrieving data of ANY type from a Container. This is like the bundle and unbundle by name. But, whereas the bundle \ unbundle by name is static on the block diagram. the Get \ Set takes in the name of the attribute that you'd like to interact with similar to the Index Array array function.
Because the container is arranged in a very predictable way, it can be presented through many different views. I've implemented a tree view that displays the Container as a tree, which mirrors the "One Parent - Many Children" model of the Container design. The tree below is a display of the "Top Level" container from the block diagram above.
In order to prevent memory leaks, call Destroy.vi. This releases the Container and all of its children recursively.
Here is a palette view of the complete API. This palette is installed from the VI Package attached below. The most common operations are promoted to the top. Namely, Create \ Destroy, Set \ Get Attribute, Add \ Get Child, and properties. The more advanced functions are located in the Utility folder.
Here are all of the API VIs:
A few of the API VIs warrant some explanation.
The Get Attribute VI returns a value by its name. I designed this VI to be polymorphic for many of the common data types, so that you won't have to cast from a variant to your desired data type.
Get Child Container(s)
The Get Container(s) VI is a polymorphic VI allowing you to get 1, N, or All (non recursive) contained containers.
Cluster To Container
The cluster has many advantages, one of which is the ability to design your datatype on the block diagram. There is a visual representation on the block diagram of your cluster vs. the Container, which has no visual representation at edit time. So I created this VI to create a Container hierarchy from a cluster:
Here's an example of the Cluster to Container:
Extending the functionality of the Container
The Container is a class based implementation "under the hood". The fact that it is classed based is hidden away by the API. The Container presents no barrier to usage if you're unfamiliar with LV Object Orient Programming. However, if you are familiar with LV Object Oriented Programming you create your own type of Container based on the work I've already done. I've created two child classes that inherit from Container named "VI" and "Control" as examples of how to override the API.
"Back end" Implementation
I wanted to spend a few paragraphs describing the implementation of the Containers. The Container fundamentally consists of three objects of the Container Intermediate Representation (CIR) class.
The three objects are intended to house key \ value pairs of three types:
1. Public Attributes
2. Private Attributes
The public attributes are those edited by using the Get \ Set Attributes API. The Private Attributes are used for information that could "muddy" the contents of the Container. For example, the "Container type" is a Private Attribute. The Children object is meant to store the references to the children contained within the parent Container.
I chose this implementation because I wanted to allow a Container to have an attribute that has the same name as a child Container. I also wanted an "easy" system for distinguishing between an attribute and a Container.
The CIR itself simply defines an interface between the Container and the organizational mechanisim that implements the key \ value lookup table. I've chosen to implement the CIR as a variant. The variant has the ability to store meta data about a value using the "Get Attribute" and "Set Attribute" primitives. That meta data just so happens to look and feel like key \ value pairs. So I've recycled the variant to act as the organizational mechanism. However, the CIR is overrideable allowing you to use other mechanisms such as XML or perhaps a data base. Using these other representations may allow easier complex querying, etc.
Getting the Containers Installed
You'll find the Containers VI Package attached below. The Container depends on the AQ Character Lineator (attached below) and the ni_lib_class_retrieval (attached below).
Lastly you'll need the free Open G toolkit which can be installed from the VI Package manager. Upon installation you'll find the Containers on the palette under "Functions". The install location is ..\vi.lib\_ApplicationTools\Containers where you will find 6 API demos.
I've also included a small test suite accessible from the Container.lvclass at ..\vi.lib\_ApplicationTools\Containers\Container\Container.lvclass. Opening the class you'll find the test suite at SubVIs \ Not on palette>>Tests>>TestSuite.vi.
I've created a custom probe which can be found at ..\vi.lib\_ApplicationTools\Containers\Container\SubVIs\Custom Probes\ContainerTreeProbe_DVR.vi
There is still a fair amount of work to be done to polish things up. There are many "todo" comments and VI Documentation needs, etc. So this is a work in progress. But I wanted to get it out there to start getting feedback. Please feel free to add your comments and requests and how you're using it.
Fixed how I call into the serializer. Now serialization works!
I've added a "tree" vi to the pallette that contains all of the API vis.
Fixed serialization of nested containers. Moved the source from vi.lib to user.lib. Source is still compiled in LabVIEW 2014.
18.104.22.168 - Deserialization is functional but under some cricumstances can be very slow. I'm still characterizing the bug.
REQUIRES LATEST vi package manager
22.214.171.124 - Serialization \ Deserialization was broken for nested containers. I've made a fix, added a test to the test suite, and reved up the major version to 2.0. Please be aware I've moved the location of the container from vi.lib to user.lib as this is not a National Instruments product. You'll find it in user.lib\_Cirrus Logic\LabVIEW Container\Source.