From Friday, April 19th (11:00 PM CDT) through Saturday, April 20th (2:00 PM CDT), 2024, ni.com will undergo system upgrades that may result in temporary service interruption.

We appreciate your patience as we improve our online experience.

LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Malleable wrapper for Traverse for GObjects

Hello dear scripters,

 

Following this idea: https://forums.ni.com/t5/LabVIEW-Idea-Exchange/Provide-a-malleable-quot-Traverse-For-G-Objects-quot-...

I created a wrapper for the classic "Traverse for GObjects.vi" that fully benefits from malleable VIs.

 

It allows to wire directly a class specifier, removing the need to write the class name manually and to later downcast the obtained references.

I used a script to generate a lookup table that gives the class name from any given VI Server refnum, whether or not the refnum is valid.

The script is included in case you want to regenerate the lookup table for newer LV versions.

 

I also merged the inputs "VI Refnum" and "Other Refnum" to allow a cleaner wiring.

 

raphschru_0-1621443979414.png

raphschru_0-1621444753969.png

 

 

 

Message 1 of 17
(2,201 Views)

Nice.

Here's an alternative way to get the class name.

cn.png

"If you weren't supposed to push it, it wouldn't be a button."
Message 2 of 17
(2,153 Views)

Nice as well, I've never thought to make it this way !

 

After doing a benchmark, it seems my method is more effective though.

My "Get GObject Class Name from Class Specifier" takes ~3.5µs in average, where yours takes ~24000µs.

 

Scripting a VI with code on-the-fly is very slow, sadly, compared to just using a lookup table, which uses purely "runtime" (non-scripting) functions.

0 Kudos
Message 3 of 17
(2,134 Views)

@raphschru wrote:

Nice as well, I've never thought to make it this way !

 

After doing a benchmark, it seems my method is more effective though.

My "Get GObject Class Name from Class Specifier" takes ~3.5µs in average, where yours takes ~24000µs.

 

Scripting a VI with code on-the-fly is very slow, sadly, compared to just using a lookup table, which uses purely "runtime" (non-scripting) functions.


True, but my method has the advantage of not needing any rework if new classes are defined in future versions of LabVIEW.  Also, in many cases, speed of scripting code is not a big issue.

"If you weren't supposed to push it, it wouldn't be a button."
0 Kudos
Message 4 of 17
(2,127 Views)

For my needs, speed is quite important.

I'm creating a tool that can generate classes with lots of property accessors, with several GObjects to modify in each.

I wouldn't like a such basic function to be way slower than the native one.

 

I agree it was more work and code for the same thing, but now it's "done".

As for the regeneration for new LV versions, personally I'm wrapping this VI alongside a tools ppl, where I use a pre-build action to regenerate necessary code.

And even for other users, I think pressing the "run" button on the given script once a year or two is not a big deal compared to how much time the process of creating scripts is taking in general 😋.

 

Also, mine can be used in the runtime engine.

0 Kudos
Message 5 of 17
(2,121 Views)

I'm glad, we talked !

I improved a bit the subVI to throw an error if the given class is unknown, asking the developer to run the script to make the update.

Still this shouldn't happen more than once in years (when NI creates new classes like for ex. maps and sets).

Message 6 of 17
(2,101 Views)

You can actually script the LUT creation to look up all the classes.

 

That is a hybrid between the static LUT and scripting a Vi each call.

 

Take a ClassSpecifierConstant, use AllTypes[]. Call another VI, with each class specifier type, run the VI with the variant magic, get the result, store it in a functional global.

 

That will take (relatively) ages to create, but the results can be cached.

 

It will take long the first time, after that it will be fast, and it will adapt to future class hierarchy changes. The results can also be stored, either in a VI or another file, and recalculated based on the LV version.

0 Kudos
Message 7 of 17
(2,071 Views)

wiebe@CARYA wrote:

Take a ClassSpecifierConstant, use AllTypes[]. Call another VI, with each class specifier type, run the VI with the variant magic, get the result, store it in a functional global.


I'm not exactly sure how you would do that.

AllTypes[] only gives you roughly a Class ID String (which is similar to my "Type Code" extracted from the variant but not exactly the same for all classes, e.g. GenClassTagFlatRef) and the Class Name.

So something is missing to link my refnum type code to the class name.

And how would you detect when the infos need to be refreshed ?

 

Everytime you use VI Server at runtime, microseconds turn into milliseconds, which I want to avoid for a such frequently used function.

 

Something really useful to do that simply would be a new function that gives directly the class name in the data type parsing palette.

Either a new VI "Get VI Server Refnum Infos" or add an output to the existing "Get Refnum Infos" with the VI Server class name.

0 Kudos
Message 8 of 17
(2,062 Views)

How's this:
cnfid.png

Note that is works with any kind of reference, not just GObjects.

"If you weren't supposed to push it, it wouldn't be a button."
Message 9 of 17
(2,047 Views)

A lot better: 100-160µs !

There's still this weird class called "GenClassTagFlatRef" that does not work because its type code (16469) is different from its class ID (122).

I don't know what this class represents, but that's another point in favor of the static LUT 🙃.

Both my script and runtime subVI use the refnum type code to link to the class name, so there's always a match.

0 Kudos
Message 10 of 17
(2,037 Views)