Jump to content

LV Object: Full Qualified Name


Recommended Posts

We couldn't find a VI or primative in LV that gives us the Full Qualified Name (FQN) for a given LVOOP object, so we came up with our own function to do this (see attachment, LV2010 SP1).

What I mean by Full Qualified Name:

This is the name of the class including it's complete namespace hierarchy, for example if the class "MyClass.lvclass" is inside "MyLib.lvlib", which itself is part of "BigLibrary.lvlib", the FQDN for the class would be "BigLibrary.lvlib:MyLib.lvlib:MyClass.lvclass".

Problems I see with the current solution:

  • It was created by reverse engineering. There might still be some special cases in which it doesn't work correctly or it might stop working in future LV versions.
  • The implementation creates a temporary copy of the object. This might slow down the application, especially when using objects that contain large data sets. This should not be necessary just to get the object's name.

Any ideas for improvements?

I am sure this functionality is already implemented inside LV, since we can see the FQN string in several places already (Variant display, object probes, ...).

Is there really no way to call this internal functionality from a LV application?

Our use case for this is a complex object oriented messaging architecture, in which we want a debug module to be able to show the difference between "Module1.lvlib:Init.lvclass" and "Module2.lvlib:Init.lvclass".

Get_LVObject_FullQualifiedName.vi

Link to comment

I don't believe there is a built in call that does this. Your code looks very similar to the code I've been using to do the same thing. As far as I know the only way to do it is decode the binary strings in the flattened data:

post-11742-0-69043700-1304513095_thumb.p

  • Like 2
Link to comment

It's good to see that the essence of your solution is the same as mine, even if you chose quite a different way for the actual decoding algorithm.

So there are at least two people who would like to have this functionality in LV.

I'm wondering if this is enough for NI to include this feature in a future LV version? rolleyes.gif

Link to comment

That's an interesting problem. I don't think there's a way to get the qualified name from an object. You can get it from a class reference, and you can figure it out from a VI reference (concatenate its library's qualified name with a colon and the VI's filename. I think the qualified name of a clone is different though.), but I can't think of any way to get a class reference from a LabVIEW Object.

(On a side note, there is a way to get a VI's qualified name given it's path. It's a private method that you need a special INI token to view. Does anyone think this would be useful?)

Link to comment

(On a side note, there is a way to get a VI's qualified name given it's path. It's a private property that you need a special INI token to view. Does anyone think this would be useful?)

Absolutely.

It would also be great to be able to get back an array of version numbers for the class hierarchy of any arbitrary Object. I at one point had code that makes an attempt using the flattened data, but wasn't terribly robust...

The qualified name and version numbers would go a long way to making any custom serialization code very robust in that we could use the embedded information in the actual class data.

Link to comment

Absolutely.

It would also be great to be able to get back an array of version numbers for the class hierarchy of any arbitrary Object. I at one point had code that makes an attempt using the flattened data, but wasn't terribly robust...

The qualified name and version numbers would go a long way to making any custom serialization code very robust in that we could use the embedded information in the actual class data.

I'm a confused what you're asking for. Are you asking for the LabVIEW version of the class hierarchy, or the class version. (LabVIEW Version is easy to get from a library reference. Class version I think we'd need AQ to weigh in on). And just to be clear: are you asking to get this information from an object or from a class reference? I'm guessing you mean object.

I guess the major hold up is converting an LV Object to a class reference. I'll ask about making the VI Path -> Qualified Name method (it's a method, not a property; I edited my original post) public in future versions.

- Mike

Link to comment

Yes, I was referring to the actual Object value (not a reference).

My understanding of an Object is there's a hierarchy of version numbers for the data in the object, insomuch as each level of an object's inheritance has an associated version number for the contained class data. Come to think of it though, the same could be said for the qnames I guess.

I suppose what would be ideal is if I could pass in any Object (value) and have a primitive that returns the qname and version of that object.

However it might be interesting to also retrieve an array of qnames/versions for each level of the object's inheritance chain. Not sure what I'd do with that information off the top of my head, but that's never stopped me from academics before.

Link to comment

I think it's great to have those functions that "convert" between a class path and a class object. That's all we need for plugin architectures.

What I don't understand is why there are no functions to help us use classes and their names in the same way they are addressed inside LV.

If I want to open a VI reference, I can chose between two ways: use the VIs path on disc (plugin) or use the VI name to get a reference to a VI that's already in memory.

Once I have the VIRef, there are properties to get both name and path.

Why is there no way to do similar things with classes?

I'd really like to have a function to get the FQN from an object.

In addition, it would help a lot to have it the other way round: Create an object with it's default value from it's FQN.

I really don't understand why I have to meddle with a path on disc, when dealing with a class that's already been loaded into memory.

Link to comment

Kudos to Daklu, I found the neat code snippet for getting the default value from a .lvclass somewhere in the LapDog source.

These Kudos belong to Aristos Queue. He's the one that shared that tip with the forum.

Link to comment

We couldn't find a VI or primative in LV that gives us the Full Qualified Name (FQN) for a given LVOOP object, so we came up with our own function to do this (see attachment, LV2010 SP1).

Ask and ye shall receive...

vi.lib\Utility\VariantDataType\GetLVClassInfo.vi

Just wire the class wire directly to the Variant input.

Shipped with LV 2010 at least, but I'm *mostly* sure it was in LV 2009. *May* have been earlier, but I *think* it was 2009.

(LabVIEW Version is easy to get from a library reference. Class version I think we'd need AQ to weigh in on).
LabVIEW version of any library (including .lvclass) can be gotten with an App method "Application:Library:Get LabVIEW File Version" without having to load the library into memory. Class version is the same as library version... if you have a reference to the class itself, you can use the "Library:Version" method.
  • Like 1
Link to comment

Ask and ye shall receive...

vi.lib\Utility\VariantDataType\GetLVClassInfo.vi

Just wire the class wire directly to the Variant input.

Thanks, but that only gives the FQN for the class of the wire, not the info for the current actual class.

fqn_test.zip

With the GetLVClassInfo.vi approach, I guess I could include a must override VI in every lvclass in which itself the GetLVClassInfo.vi gets called... but then I could just return a string constant since I know the value at edit time.

Link to comment

Thanks, but that only gives the FQN for the class of the wire, not the info for the current actual class.

fqn_test.zip

With the GetLVClassInfo.vi approach, I guess I could include a must override VI in every lvclass in which itself the GetLVClassInfo.vi gets called... but then I could just return a string constant since I know the value at edit time.

*head smack* I forgot about that. It's the type descriptor included in the variant, which is the wire... it doesn't delve into the object.

Somehow I did get the right type descriptor into the variant. Now, if only I could remember how I did that...

Link to comment

I don't think there's a way to get the qualified name from an object. You can get it from a class reference...

I suppose what would be ideal is if I could pass in any Object (value) and have a primitive that returns the qname and version of that object.

A bit late to the conversation I know, but why can't you encapsulate the reference to get the desired effect (assuming Class exists on disk)?

I remember I had to do something similar when scripting once.

Don't know it it helps?

Cheers

-JG

Here is an example project

post-10325-0-95145700-1305206854_thumb.p

The VI's API accepts a LabVIEW Object as an input

post-10325-0-82017200-1305206481_thumb.p

Behind the scenes it just uses a Class Reference but that is encapsulated

post-10325-0-55517400-1305206849_thumb.p

Here are the results

post-10325-0-77892700-1305206483_thumb.p

I also tested it as a build and these properties are available in the LV Runtime.

FQN_LV2009.zip

Code is in LV2009

Link to comment

Thanks for another idea!

Unfortunately this approach is to slow for my use case. My first benchmark showed about average runtimes of about 300ms for the file/project api and about 0.1ms for the flatten/parse version.

Since my goal is to analyze every message object sent inside the application, speed is very important.

Link to comment

Thanks for another idea!

Unfortunately this approach is to slow for my use case. My first benchmark showed about average runtimes of about 300ms for the file/project api and about 0.1ms for the flatten/parse version.

Since my goal is to analyze every message object sent inside the application, speed is very important.

Our use case for this is a complex object oriented messaging architecture, in which we want a debug module to be able to show the difference between "Module1.lvlib:Init.lvclass" and "Module2.lvlib:Init.lvclass".

Yes I forgot to add the footprint is large, and then reread your use-case, sorry.

On a side note, since the Class is already in memory maybe there is a way to get e.g. a cache'd reference rather than open a new one?

Link to comment

On a side note, since the Class is already in memory maybe there is a way to get e.g. a cache'd reference rather than open a new one?

For that matter, you could just create a lookup table with each default object as the key and the fully qualified name as the value. You'd have to use Jon's technique to get the FQN the first time a message object is seen but the rest of the time it would be a much faster operation.

Link to comment

The problem then is, that I could choose between blocking the program at every unkown object while getting the FQN (including high cpu load, visible spinning mouse cursor wheel)

and additional application startup time of at least 30++ seconds by preloading/caching all lvclasses/FQNs (timing after limited testing, 65-80 LVOOP-based commands).

I guess I'll stick with the flatten/parse version until LV gets a real object to FQN primitive.

Link to comment

I wouldn't recommend the library refnums for anything other than editor support. They were never intended to be in the runtime engine -- they got added in LV 2009 to support TestStand talking to LabVIEW, and, honestly, I think including them is a bit misleading. The library refnums all go through the project interface. The functionality that they were designed to promote is not the runtime reflection that an OO programmer might be looking for, but instead for the editor capacities that a LV add-on author might be looking for. They require a swap to the UI thread, which is an obvious drawback.

I haven't found any place where I actually get the qualified name from an object. The code that I thought I had done the "to variant" conversion trick apparently I found a different workaround and ended up not needing the qname at all. So the Flatten To String is still your best approach in all shipping versions of LV, as icky as that may be.

There just hasn't been much request for the reflection API, and for most APIs, the path has been sufficient since any API designed to be used in a running VI (as opposed to a scripting editor tool) doesn't have to worry about classes that have never been saved to disk.

Link to comment

There just hasn't been much request for the reflection API, and for most APIs, the path has been sufficient since any API designed to be used in a running VI (as opposed to a scripting editor tool) doesn't have to worry about classes that have never been saved to disk.

The lack of any reflection in LabVIEW OOP has been one of my harshest criticisms of the system since it's inception. I for one would welcome our new reflective overlords...

I'm not saying I don't like LVOOP, I love it. But there are some features that are surely lacking compared to more mature OOP implementations. We can be forgiving though since LVOOP is in its infancy. The fact that it even exists, I consider a triumph worthy of praise to those at NI who pushed it through development.

-m

  • Like 2
Link to comment

The lack of any reflection in LabVIEW OOP has been one of my harshest criticisms of the system since it's inception. I for one would welcome our new reflective overlords...

I'm not saying I don't like LVOOP, I love it. But there are some features that are surely lacking compared to more mature OOP implementations. We can be forgiving though since LVOOP is in its infancy. The fact that it even exists, I consider a triumph worthy of praise to those at NI who pushed it through development.

Agreed on all points. I hope NI continues to expand LVOOP's capabilities to bring it more up to date with other modern languages.

Link to comment

I wouldn't recommend the library refnums for anything other than editor support. They were never intended to be in the runtime engine -- they got added in LV 2009 to support TestStand talking to LabVIEW, and, honestly, I think including them is a bit misleading. The library refnums all go through the project interface. The functionality that they were designed to promote is not the runtime reflection that an OO programmer might be looking for, but instead for the editor capacities that a LV add-on author might be looking for. They require a swap to the UI thread, which is an obvious drawback.

To be honest, I was surprised it worked in the run time (yes, my previous use cases were scripting).

However, I always enjoy reading about these LabVIEW tidbits. thumbup1.gif

Link to comment

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.