Jump to content

Refnum type propagation


mje

Recommended Posts

Is there any sort of LabVIEW voodoo that allows you to propagate type information for a refnum through a VI?

I have VIs which take generic Control Refnums in then out, but the problem is the output always looses it's type info. So I can't ever use the output to wire up to another VI which operates on a more specific class, even if I supplied that class to the input.

Example, this little bit of code I've been using for ages which defers panel updates which I'm sure many of us can relate to in one form or another:

post-11742-034420000 1287759898_thumb.pn

I have VIs that operate on refnums of one type or another (especially XML) that I'd really like to not have to always "branch off" the refnums to be able to operate on them. Is there a way to do this, sort of similar to how type info is propagated for LabVIEW objects?

I'll add I'm aware I can just make a ton of polymorphic VIs. I've even done as much. But it's kind of kludgy, and requires an implementation for every kind of refnum...

Link to comment

I'm not sure what your asking here. Type information? If you mean the controls class (e.g boolean, string etc) then it is propagated (if you inspect the class name you will see it).

If you mean you cannot connect a parent class refnum to a child class refnum and have it automagically choose the appropriate refnum then no. Because "classic" Labview doesn't support run-time polymorphism. You have to go to OOP and use dynamic despatch (which wouldn't be much different from creating your polymorphic VI).

The only way I know of that you could achieve a similar behaviour in classic LV is to make all your refnums variants and coerce to the specific class within each VI. But then you can connect anything to anything so it wouldn't flag up (for example) that you had connected a real control rather than a refnum until you ran it.

Edited by ShaunR
Link to comment

Is there any sort of LabVIEW voodoo that allows you to propagate type information for a refnum through a VI?

I have VIs which take generic Control Refnums in then out, but the problem is the output always looses it's type info. So I can't ever use the output to wire up to another VI which operates on a more specific class, even if I supplied that class to the input.

Example, this little bit of code I've been using for ages which defers panel updates which I'm sure many of us can relate to in one form or another:

post-11742-034420000 1287759898_thumb.pn

I have VIs that operate on refnums of one type or another (especially XML) that I'd really like to not have to always "branch off" the refnums to be able to operate on them. Is there a way to do this, sort of similar to how type info is propagated for LabVIEW objects?

I'll add I'm aware I can just make a ton of polymorphic VIs. I've even done as much. But it's kind of kludgy, and requires an implementation for every kind of refnum...

Your code has a memory leak. The reference created by OwningVI needs to be closed. I have a similar bit of code and it took me half a day to track down that memory leak. You can use the desktop execution trace to find hanging references (which didn't exist back then).

Link to comment

Are you sure about that memory leak? I thought one should only close refnums which you explicitly open?

Haven't played with the desktop execution toolkit yet...

Also, with regards to Shaun's questions, first please see the screenshot. Code used to generate it is also attached.

post-11742-060661400 1287770377_thumb.pn

If you mean you cannot connect a parent class refnum to a child class refnum and have it automagically choose the appropriate refnum then no. Because "classic" Labview doesn't support run-time polymorphism. You have to go to OOP and use dynamic despatch (which wouldn't be much different from creating your polymorphic VI).

I'm actually looking for the opposite of run-time polymorphism. I'd like a way for static compile time info to somehow be propagated. Take for example how you can wire up a parent method of an OOP class in the middle of a child class wire, without the wire being coerced to a parent class (shown in the bottom of the screenshot). LabVIEW is smart enough with objects to be able to figure out when type information can be propagated through a VI call with objects at compile time, it would be wonderful if that could also apply to refnums...

Is that more clear? I'll point out that this is more of an "I wish it existed" post than "Is there a way to do it?" post...

RefnumDemo.zip

Link to comment

Are you sure about that memory leak? I thought one should only close refnums which you explicitly open?

I'm certain. The explicitly open is generally true in my experience, but Owning VI is an example of when it's not true. The desktop trace confirms it, if you cast the ref to an integer, its value changes for each call, and if you run it in a tight loop memory use will grow without bound (no super fast though, it's only leaking a pointer sized int).

The desktop trace toolkit could be better (like tracking which event in the event structure was triggered). The tracing is good for debugging heavily multithreaded code. The ability to find unclosed references and check how LabVIEW is really allocating memory make it uniquely useful.

Link to comment

Can you use just generic control references for controls/indicators, and calls to To More Specific Class inside of each vi with a specific type?

If To More Specific Class errors, the cast is invalid, and you can behave appropriately.

Just a (possibly fever induced) thought... a quick and dirty sample seemed to work for me.

Joe Z.

Link to comment

Can you use just generic control references for controls/indicators, and calls to To More Specific Class inside of each vi with a specific type?

If To More Specific Class errors, the cast is invalid, and you can behave appropriately.

Just a (possibly fever induced) thought... a quick and dirty sample seemed to work for me.

Joe Z.

Yeah, I've seen something of that nature before with a while loop and a case statement - cover all the cases you think you'll need. It is definitely a kludgey solution, but a solution nonetheless.

Link to comment

Is there any sort of LabVIEW voodoo that allows you to propagate type information for a refnum through a VI?

This is sort of a non-answer, but it helps me and I think has merit. What I always do in this situation is not pass the refnum back out from the subVI. There is only a refnum input. This prevents the caller from accidentally doing the cast to a more generic class. It has the downside that the calling code is a little uglier, since it can't railroad the refnum wire through for multiple calls to such subVIs.

Link to comment
I'm actually looking for the opposite of run-time polymorphism. I'd like a way for static compile time info to somehow be propagated. Take for example how you can wire up a parent method of an OOP class in the middle of a child class wire, without the wire being coerced to a parent class (shown in the bottom of the screenshot). LabVIEW is smart enough with objects to be able to figure out when type information can be propagated through a VI call with objects at compile time, it would be wonderful if that could also apply to refnums...

Is that more clear? I'll point out that this is more of an "I wish it existed" post than "Is there a way to do it?" post...

I see what you mean.

But your "Class" example isn't exactly analogous to the VI example (just being picky :P ).

If you inspect your middle VI, you will see there is a coercion dot. So the equivalent class implementation would be

As you can see. this also has the same issue. The class example is really analogous to creating a polymorphic VI

Edited by ShaunR
Link to comment

I see what you mean.

But your "Class" example isn't exactly analogous to the VI example (just being picky :P ).

If you inspect your middle VI, you will see there is a coercion dot. So the equivalent class implementation would be

As you can see. this also has the same issue. The class example is really analogous to creating a polymorphic VI

I think what is wanted is that there is not a coercion dot, because the coercion never happens. The type should be propagated across the subVI without changing.

Link to comment

I think what is wanted is that there is not a coercion dot, because the coercion never happens. The type should be propagated across the subVI without changing.

Agreed. It would be nice. But it kind-a indicates that coercion does happen. The VI's cannot statically change the control refnum without using polymorphism so it has no choice but to either give a broken wire or coerce the data on the wire to a compatible type.

It gets even worse if you pop-up the right click menu on the boolean control ref and select "Include Data Type". You won't even be able to connect it to a standard boolean control ref. You will have to convert it to Bool(Strict) first.

Link to comment

First, to answer the original question, this can be done using XNodes, but that's not officially supported and I never really played around with them. There should be an example somewhere on LAVA. This can also be done with express VIs, as shown in this thread, but I never played around with that either:

http://lavag.org/topic/4007-anything-to-whatever-lv-71

Second, please go to the idea exchange and vote for this idea -

Provide a better way to implement a polymorphic VI

You should read this to see why this is not likely to happen soon, though:

http://forums.ni.com/t5/LabVIEW-Developers-Feature/Now-available-for-download-quot-Randomize-1D-Array-vi-quot-that/m-p/1159329#U1159329

Third,

Agreed. It would be nice. But it kind-a indicates that coercion does happen.

What Jarrod was saying is that your example is flawed because you upcast the object yourself. If you just wire the child class directly into the parent VI it would propagate through just fine (assuming there's no overriding VI in the child class).

This, of course, can only be done today using LVOOP.

Link to comment

What Jarrod was saying is that your example is flawed because you upcast the object yourself. If you just wire the child class directly into the parent VI it would propagate through just fine (assuming there's no overriding VI in the child class).

This, of course, can only be done today using LVOOP.

Well. I read "I think what is wanted is that there is not a coercion dot, because the coercion never happens." to mean that even though there was a coercion dot, it wasn't being coerced. The comparison example was just to show that even in OOP, if you coerce (yes you have to do it manually) then the result is the same.

Edited by ShaunR
Link to comment

Well. I read "I think what is wanted is that there is not a coercion dot, because the coercion never happens." to mean that even though there was a coercion dot, it wasn't being coerced. The comparison example was just to show that even in OOP, if you coerce (yes you have to do it manually) then the result is the same.

The result is not the same with OOP. Check this example where the wires for parent and child classes are different.

post-10515-080645900 1287927815_thumb.pn

The same thing is not true with VI server references. A boolean reference that runs through a control reference will still contain the boolean reference number, but the wire will be a control reference. You need to recast to boolean to be able to call methods that act on booleans.

Link to comment

The result is not the same with OOP. Check this example where the wires for parent and child classes are different.

post-10515-080645900 1287927815_thumb.pn

The same thing is not true with VI server references. A boolean reference that runs through a control reference will still contain the boolean reference number, but the wire will be a control reference. You need to recast to boolean to be able to call methods that act on booleans.

Exactly, François, I think you did a better job explaining what I was trying to say.

Link to comment

The same thing is not true with VI server references. A boolean reference that runs through a control reference will still contain the boolean reference number, but the wire will be a control reference. You need to recast to boolean to be able to call methods that act on booleans.

Yes. Because it is coerced!

Edited by ShaunR
Link to comment

Right! But it would be good if the compiler were smart enough to know not to coerce it, just as it does for classes.

Indeed. That's why I said it would be nice earlier.

Although. If you think about it. When you open up the VI with the control ref. What should it display? The VI itself doesn't know what it's connected to; only the owning VI. The way "Classic" labvVew gets round this is the owning VI selects a VI with a compatible terminal and the only way you can tell it what VIs to select from is by defining a polymorphic VI. The fall-back is to coerce it, then a broken wire.

Furthermore. If you think about classes (static ones). The owning VI is selecting the child class which you have previously defined. So in this instance there is no difference between a polymorphic VI and a Class (well. There maybe some but I can't think of any). After all. If you defined the "Boolean" class such that it wasn't a child (equivalent to a VI not attached to a polymorphic instance). You wouldn't be able to connect it either and Labview wouldn't even try to coerce it..

Link to comment

I see where you're coming from. Agreed.

When I open up the VI with the generic control ref, I'd expect it to only know about the generic control ref. That's the interface the VI has set by virtue of its connector pane. What would be ideal though is if the VI had some way of recording continuity between the input and output. This facility does exist in LabVIEW, for example with dynamic dispatch method for classes it is indeed required. I have no idea how this gets sorted out for static methods given that the same requirement is not in place (maybe internally the compiler is still aware of in/out continuity?). It would be nice if refnum in/outs had the same functionality, or you could have another type of in/out connector that mimics the behavior of classes for refnums, such that explicit coercion does not happen when passing child refnums to parent methods.

I suspect though that the details lay in how refnums are actually implemented. Something tells me we are not dealing with a strict inheritance implementation which will always force a coercion: there is no actual polymorphism happening with refnums (or dynamic dispatching in LabVIEW language). It's probably the same fundamental difference which results in the limitations imposed on class DVRs which prevent dynamic dispatching.

Now that I've thought this through, I suppose it makes sense why it is the way it is. I still don't like it though...

Link to comment

I see where you're coming from. Agreed.

When I open up the VI with the generic control ref, I'd expect it to only know about the generic control ref. That's the interface the VI has set by virtue of its connector pane. What would be ideal though is if the VI had some way of recording continuity between the input and output. This facility does exist in LabVIEW, for example with dynamic dispatch method for classes it is indeed required. I have no idea how this gets sorted out for static methods given that the same requirement is not in place (maybe internally the compiler is still aware of in/out continuity?). It would be nice if refnum in/outs had the same functionality, or you could have another type of in/out connector that mimics the behavior of classes for refnums, such that explicit coercion does not happen when passing child refnums to parent methods.

I suspect though that the details lay in how refnums are actually implemented. Something tells me we are not dealing with a strict inheritance implementation which will always force a coercion: there is no actual polymorphism happening with refnums (or dynamic dispatching in LabVIEW language). It's probably the same fundamental difference which results in the limitations imposed on class DVRs which prevent dynamic dispatching.

Now that I've thought this through, I suppose it makes sense why it is the way it is. I still don't like it though...

Indeed. Whats missing is that a generic refnum should have the option to "adapt-to-type" instead of being coerced. Properties and methods can already do this, so if the control refnum could also adapt, all the properties and methods inside your VI would follow suit. In effect, you would have a polymorphic VI without having to declare all the sub-vis (for these types of VIs at least).

Edited by ShaunR
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.