We can access the TD from the "Flatten to string" function, right-clicking and choosing "Convert 7.X data" if using LV 8 or above. TDs are internal descriptions of data being sent places within LabVIEW. In essence, they are an inherent part of the data type. We all know that if we connect a DBL to a SGL, we get Coercion. This tells us that we have a data change going on. If we connect two DBLs however, we don't see a coercion dot, which is of course expected.

Does this mean that we have the exact same data type as before. Not neccessarily. If we look at the TD, it may be different.

The clue is that the TD contains the NAME also, so the TD of two otherwise identical controls, but with different names have distinct TDs. So we can see that by accessing the TD of a control (or wire) we can differentiate not only based on data type, but also based on NAME. This is important for later.

In AdditionI'm also going to assume you're familiar with producer-consumer designs. If not, you can read about them here.

For a list of past nuggets, see here.If you want to write a nugget yourself, see here.

In a producer-consumer
design, each distinct command being passed between producer and
consumer has a corresponding value on an enum (I prefer Enums over
Strings). Clustering this enum with a variant (Which can conatin any
type of data) gives us a single universal messaging data structure of
function name and variable data content. By passing such a cluster
with the correct enum and variant contents from the producer loop, we
can call any of the implemented commands in the consumer loop.Please ignore my spelling mistakes!

In
this code example, we use some simple shape definitions to draw a
picture. We can choose between circle, square or triangle. We can
also set colour, rotation, X-Position, Y-Position and size.

PRODUCER

On
to this example implementation: when looking at the producer loop, we
see that basically one method is being called regardless as to which
shape characteristic we're changing. Depending on the change being
made, the only difference in the message queued is the data type.

Sending a cluster:

Sending a DBLSending a U32

CONSUMER (Please reference the included LLB for these steps)

A: Once the consumer loop receives the data in the queue, unbundling it gives us the function name and the variant data.

We're
interested in the "Draw Shape" case. We're actually handling lots of
different distinct "function calls" within this single state. We can
pass the X-Position (DBL), Y-Position (DBL), rotation (DBL) and so on
within the variant. The job of this single state is to detect which
case we're using and react accordingly. This is kind of similar to
having multiple API commands such as:

DrawShape(X-Position DBL);DrawShape(Y-Position DBL);DrawShape(Rotation DBL);DrawShape(Color U32); and so on

B:
In order to first detect which datatype is being received, we need to
read the TD of the data WITHIN the variant, not of the variant itself.
We then "clean" the TDs being used (See caveats below) and can then do
a simple search for a "registered" data type. The array input for the
"Search 1D Array" is generated on the block diagram. Consult the code
for reference.

C: If one is found, a subsequent case
statement (Here depending on the index of the found TD) is responsible
for incorporating this data into the correct cluster for our drawing
routine. At this stage, we have a routine which automatically receives
a single command with different data and then incorporates this data
into the proper place in a pre-defined cluster.

D: The actual drawing routine always works with this same pre-defined cluster.

Run the VI to see how this works in practise.

The
act of incorporating the data into a standard cluster COULD be
automated for any given data types and the differences between the same
function called with different parameters COULD be a lot more
significant than I show here. It depends on the application in
question. A universal "Include data" along these lines is feasible
along and would probably be a nice exercise in getting to know LV data
types.

I hope I have explained the principle behind my idea. I hope some find it useful. I know I do, regularly.

For a list of past nuggets, see here.If you want to write a nugget yourself, see here.

I've
been told that this method is more like "Virtual functions", and not
"Function Overloading", one being checked by the compiler, the other at
run-time. Either way.....

Hint:We are generating our
"registered" TD array at run-time. Any changes to the representation
or name of any of the controls on the FP will change the outcome of our
TD comparison. This may break the code.

Since the name of the
control is stored within the TD, a control with the same data type, but
different name will NOT be found when comparing the TDs. Please try
out the "colour box" control on the FP. Since the control we are
comparing with is called "color box" (no "U"), the comparison will
fail. The message will be queued, but since the data type is
unrecognized, the data is not used.

Caveats: Type
descriptors have reserved bits. These need to be removed to enable
comparisons. This is done in the "TD Clean" VI. This is a simple
version of a "proper" version.

Type descriptors are not
necessarily tied to a control. They are inherent to data in LabVIEW.
This said, non-control TDs differ from those of Control TD in that the
name of the control is missing from the non-control TD. This means
that we need to use a terminal within the event structure (which is
good practice anyway) as the "newval" data has a different TD.....

Type
descriptors contain the data type and control name(s) of any units
within the control. This is accessible from any wire originating from
a control, even if it has been converted to variant. To access the
correct TD from a variant, we must use "Variant to flattened string".
This will return the TD of the data type WITHIN the variant, not of the
variant itself. This function has the unfortunate side-effect that it
forces a buffer allocation. For large data sets, this might be
problematic.

Homework: Change the name of the "colour box"
control on the front panel to "color box" (as in the cluster) and
re-run. The solitary colour box now works.

Change the data representation of any single control and see how this affects the functionality.

Attach
the "newval" terminal to the "Queue element" instead of the control
terminal (Producer loop). See how the TD changes and the code breaks.

(for
NI) Please give us the means to access the TD without creating a data
copy. And please don't get rid of the TDs completely!!!

(for
NI) Even better would be native support for overloading such
functions. Or the ability to generate Polymorphic VIs where not only
the data type is varied, but also the name (i.e. the FULL TD).....

For a list of past nuggets, see here.If you want to write a nugget yourself, see here.

I do like the idea of a universal scheme to passing data to the consumer loop. And variant seems to be the most versatile way of doing this.

For some reason, I remember during one of the NI-LV course that the instructor mentionned staying away from variants as a universal container for different data types. I'm looking through my notes to find out why (hopefully I noted a reason) >> anyone from NI care to comment???

Don't get me wrong... I do like the approach. Personally, I think it's wonderful!! It sure simplifies building a universal Event Structure / machine.. One that is very easy to add on more functionality.

Nice nugget, although I'm also a bit afraid of something which already requires relying on old versions. I don't think the support would disappear anytime soon, but it wouldn't be developed either.

Another point - relying on undocumented features could give you some headaches later on. For example, in a recent thread there was someone complaining that the DB toolkit didn't work. Why? Because when adding variants to the DB it relied on the internal structure to determine the size of the data. When that internal structure, the toolkit broke and NI didn't find it because they didn't test for that case.

JLV, one good reason for not using variants is that they are not strictly typed, so you can only catch errors at run-time. This is also something that speaks for them (for example, when you want to create this type of architecture), but there are other ways to do this as well.

I too use them, but I didn't want to make a Nugget dependent on external tools.....

It doesn't have to depend on them, but I see nothing wrong with taking some shortcuts. As a matter of fact, having OpenG as the subject for a future nugget, just to raise awareness is on my list of potential nuggets.