Jump to content

LVOOP object control element accessing via bundle vs property node


Recommended Posts

I wrote a Labview program that uses LVOOP that worked correctly. I then modified a class to allow access to one of the object control elements via a property node outside of a member method VI. As a result, a member method VI that writes to that element using named-bundle ceased to function correctly. No broken arrow nor broken wire, but the object output of the VI did not include the new value in that cluster element. I cured the problem by writing to the element using a property node instead of named-bundle. But I shouldn't have had to do that because I should be able to update elements using cluster functions if on the diagram of a member method VI, right? Do you think this a Labview bug, or is LVOOP supposed to work this way?

 

LV 2012 SP1 f5 on Windows 7 32-bit.

 

Thanks. -Joe

Link to comment

I am a bit confused so I will write it as I understand it.

 

Your class has some private data that has in it a cluster.  I think this is what you call the object control element.

You added a accessor method to Read this cluster as a complete block (not the element of the cluster).  I think this is your property node. And it is used by some member method vi.

In this member vi, you used the Read <cluster> property node and then the Bundle By Name primitive to set the value of the desired element.

At the end of this, you expected that the value supplied to Bundle By Name would be in the object's private data cluster.

 

If that is correct, did you actually write the cluster obtained from the property node (the Read <cluster>) and changed the element value back to the object's private data? For instance using a Write <cluster> method (you would have to create such a method).

 

Remember this is all data flow.  The Read makes a copy of the data from the object's private data.  If you change your copy, you need to write it back.

 

If I am off base here, sorry, perhaps you can correct my interpretation.

Link to comment

Hi Joe,

 

Do you have a little bit of code that you can show the problem? I can't quite tell if you're running into some serious issues with LabVIEW or perhaps just aren't getting what you'd expect from your code. I've seen really strange corruption issues creep up before and also observed behavior with properties, but it's hard to tell what may be happening in your case based on what you've said. I'll also note those threads are dated a few years ago, though I've never worked with 2012, I've generally had none of these issues with the 2011 development environment.

 

...the object output of the VI did not include the new value in that cluster element.

 

This statement however does set off alarms in my head as I've seen this behavior (first linked topic). My recommendation would be to take your top level VI that starts everything and do a full recompile (click the Run button while holding Shift + Ctrl). Sometimes these the observation that a VI is returning the wrong data is only a symptom of an issue high up the call stack: there's nothing wrong with the VI in question, rather something else is passing it bad data.

 

Cheers,

M

Link to comment

Thanks for the help.  These pictures illustrate the problem.  It's a large Labview program with hundreds of subVIs.  It worked correctly.  Inside a class member method VI, it updated a class object element 'nPixels' using a bundle by name:

 

AutoMeasure001

 

Later, I made nPixels accessible via Property Node to VIs outside of the class.  Then, the program no longer worked correctly.  I discovered that subVIs that wrote to specific object elements using bundle-by-name did not have the new value preserved in the calling VI.  If I probe the object wire coming out from the bundle-by-name, it has the new value correctly.  But if, on the calling VI's diagram, I probe the object wire coming out of the subVI, it does NOT have the new value.

 

The workaround was to replace the bundle-by-name with a Property Node write:

 

AutoMeasure002

 

and then everything worked correctly again.

 

-Joe

Link to comment
Thanks for the help.  These pictures illustrate the problem.  It's a large Labview program with hundreds of subVIs.  It worked correctly.  Inside a class member method VI, it updated a class object element 'nPixels' using a bundle by name:

 

 

 

Later, I made nPixels accessible via Property Node to VIs outside of the class.  Then, the program no longer worked correctly.  I discovered that subVIs that wrote to specific object elements using bundle-by-name did not have the new value preserved in the calling VI.  If I probe the object wire coming out from the bundle-by-name, it has the new value correctly.  But if, on the calling VI's diagram, I probe the object wire coming out of the subVI, it does NOT have the new value.

 

The workaround was to replace the bundle-by-name with a Property Node write:

 

 

 

and then everything worked correctly again.

 

-Joe

This is a complete guess, but is it possible that you mistakenly have a nPixels data member in both a parent and a child, and you are setting/accessing the wrong one? My guess is this is not it as Michael suggests he has seen similar behavior before, but it is worth throwing out there.

Edited by GregFreeman
Link to comment
This is a complete guess, but is it possible that you mistakenly have a nPixels data member in both a parent and a child, and you are setting/accessing the wrong one? My guess is this is not it as Michael suggests he has seen similar behavior before, but it is worth throwing out there.

 

Good question, thanks.  The method VIs are all dynamic-dispatch-override VIs.  Each child class object contains all the elements of the parent class object plus some elements specific to the child.  nPixels is common to all the child classes so is in the parent class, too.  Should I have kept out from the child class cluster all the elements of the parent class cluster?  I don't think LVOOP works that way, does it?

 

Earlier in the program flow, the parent object wire is cast to the required child object using 'Get LV Class Default Value.vi' and 'To More Specific Class' function.

 

Thanks. -Joe

Link to comment
Good question, thanks.  The method VIs are all dynamic-dispatch-override VIs.  Each child class object contains all the elements of the parent class object plus some elements specific to the child.  nPixels is common to all the child classes so is in the parent class, too.  Should I have kept out from the child class cluster all the elements of the parent class cluster?  I don't think LVOOP works that way, does it?

 

Earlier in the program flow, the parent object wire is cast to the required child object using 'Get LV Class Default Value.vi' and 'To More Specific Class' function.

 

Thanks. -Joe

You've done it correctly. I wasn't implying anything with regards to the way LVOOP works, but instead was referencing a bug I caused. Here is an example:

 

I just know in the past I have put something in a child class, then decided it needed to be in the parent. So, I moved it to the parent but forgot to delete it from the child when I did so. Now I had a variable A in my parent and a variable A in my child. Then, down the road, I started setting variable A in the child class, but accessing variable A that was in the parent, which just kept returning a default value. Does that make sense? It was a bug entirely inflicted by me on myself  :angry:

 

Edit: threw together a quick example of what I had done, and attached it. Not using property nodes, but you get the idea. Pretty confident this isn't causing the issue you are seeing though, but I'll add it for clarification to my rambling anyways.

New folder.zip

Edited by GregFreeman
Link to comment
Later, I made nPixels accessible via Property Node to VIs outside of the class.  Then, the program no longer worked correctly.  I discovered that subVIs that wrote to specific object elements using bundle-by-name did not have the new value preserved in the calling VI.  If I probe the object wire coming out from the bundle-by-name, it has the new value correctly.  But if, on the calling VI's diagram, I probe the object wire coming out of the subVI, it does NOT have the new value.

 

The workaround was to replace the bundle-by-name with a Property Node write.

 

...I just made a simpler project (in LV 2013 f2) that duplicates this same sequence of actions, and I did not get the incorrect behavior.  So either it was a temporary corruption or it was fixed in 2013.

 

Thanks. -Joe

Link to comment
I discovered that subVIs that wrote to specific object elements using bundle-by-name did not have the new value preserved in the calling VI.  If I probe the object wire coming out from the bundle-by-name, it has the new value correctly.  But if, on the calling VI's diagram, I probe the object wire coming out of the subVI, it does NOT have the new value.

 

The workaround was to replace the bundle-by-name with a Property Node write

 

 

Following onto mje's linked threads, your problem here seems backwards from normal -- replacing a Property Node accessor with a Bundle by Name is more likely to solve problems than cause them.

 

Is it possible that the wire is not connected as it appears to be connected? On the original diagram, you right click the wire and "Clean Up Wire", is the output terminal connected to the output of the Bundle by Name, or is it a branch of the original wire (with the joint hidden by the node)?

 

post-17237-0-89580200-1392964607_thumb.p

Link to comment

Yah, that can be a gotcha in Labview.  That's not my problem, though.  The problem happened in several subVIs that worked correctly at first.  Then, without modifying those subVIs, I made some properties accessible to the outside world via Property Node, and at that point the application and those subVIs no longer worked correctly as described in the above postings.

 

Thanks. -Joe

Link to comment

That's very  strange you posted this today. I had the exact same issue this morning and i was about to pull my hair out.  I had a bundle by name that just seemed to refuse to actually accept the data that was being passed to it.  I could probe the wire of the data being passed to it and see it was there, but when i probed the class wire after the bundle, the value was not updated.  

 

This was in Labview 2013.  In addition, when i tried to CTRL-Shift-Run, labview would hard crash to desktop with no apparent error message.  I assumed it was some very strange corruption happening on the compiling of the code.  

 

My situation was very similar.  I was un-bundling data from Class A,another class in this case, reading a public value out of that class using a property node and then bundling that data back into the main Class A.  

 

The strange part was that i was i was actually bundling another piece of information into that class and it was being accepted but another was not.  In the end, to fix the issue i had to use a completely separate bundle by name further down the wire.  

 

I can't seem to attach a pic of my code since this is my first post 

Link to comment
  • 4 weeks later...
  • 4 weeks later...

I'm not able to replicate the issue by making a smaller set of VIs.  In new VIs and classes I put together using the same technique, all the Bundles and Unbundles work correctly.  My project that has the bugs is large and connects to in-house-made external DLLs and .NET assemblies, so there is a lot to install in order to not have a broken arrow and I can't really send it outside.  Mass compiling did not help.  I continued to run into bugs until I made all elements of the class cluster accessible via Property Node and then replaced ALL Bundles and Unbundles with Property Node writes and reads in all member method VIs.  After doing that, the bugs were cured.

 

If I send to NI the .lvclass file alone, can NI analyze it for corruptions?

 

Thanks. -Joe

Link to comment

Just to chip in here, I recently had the same problem (2013 SP1). Bundling in a "variable" wire did not cause the class output "cluster" to be updated. Bundling in a constant (in this instance it was a string) did cause the "cluster" to be updated correctly.

 

Probably entirely related, editing some code in this class would cause the IDE to hard-crash, so I figure I just managed to get my code in a state that was not consistent.

 

I fixed my problem by deleting the VI that caused the crash and re-creating it from scratch. I think the inconsistency happened when I renamed a class VI to something that had previously existed in that class.

Link to comment
  • 1 month later...
Just to chip in here, I recently had the same problem (2013 SP1). Bundling in a "variable" wire did not cause the class output "cluster" to be updated. Bundling in a constant (in this instance it was a string) did cause the "cluster" to be updated correctly.

 

Probably entirely related, editing some code in this class would cause the IDE to hard-crash, so I figure I just managed to get my code in a state that was not consistent.

 

I fixed my problem by deleting the VI that caused the crash and re-creating it from scratch. I think the inconsistency happened when I renamed a class VI to something that had previously existed in that class.

 

Eeesh Neil,

 

Did you ever get to the bottom of this or just re-create and move on. I've got the same issue here this morning (least I think it's the same). Constant bundled in updates the cluster, wiring in a "variable" does not. Probed the wire, input data is valid. 

 

Re built the VI and moved on. I had seen crashes too when making changes to the class so perhaps like you we've managed to upset LabVIEW.

 

I'm moving on the next issue but this is leaving me with a prickly sensation on the back of my neck, all is not well somewhere.

Link to comment
Eeesh Neil,

 

Did you ever get to the bottom of this or just re-create and move on. I've got the same issue here this morning (least I think it's the same). Constant bundled in updates the cluster, wiring in a "variable" does not. Probed the wire, input data is valid. 

 

Re built the VI and moved on. I had seen crashes too when making changes to the class so perhaps like you we've managed to upset LabVIEW.

 

I'm moving on the next issue but this is leaving me with a prickly sensation on the back of my neck, all is not well somewhere.

Sorry Chris, never got the the bottom of it. I am glad I had read this thread before it happened to me as otherwise I would have thought I was going crazy!

 

I have a suspicion (based only on a tiny bit of evidence) that the problems arise when renaming class VIs. I am pedantic about having the VI name match what the VI is actually doing, so will often rename a VI as my code/API iterates. Now normally this does not cause any problems, however I have seen instability when I rename a VI to something that a different VI used to be called. It's like there is some form of stale code path somewhere that gets invoked.

 

I did not try cleaning out my VI Object cache, that may have helped...

 

Also, in the past (LV2011) I had some success with a crashing class by erasing the class mutation history. Again I did not try this this time as it was just quicker to recreate the offending VI from scratch and move on.

Link to comment

I think that my problems may have started after trying to change the folder location of my class hierarchy of VIs and supporting files.  The project displayed conflicts.  I couldn't figure out how to resolve the conflicts, so I was forced to put everything back in its orginal folder location on my machine.  It's a dangerous situation that we can't smoothly relocate nor rename OOP VIs, files, and folders.  NI needs to test and debug all common code maintenance maneuvers with OOP.

 

I could probably fix my problems by reconstructing all my classes and their VIs, but that is a huge amount of work for what I've built.  For this project, it looks like I'll have to stick with only accessing object elements using the Property Node.

Link to comment
I think that my problems may have started after trying to change the folder location of my class hierarchy of VIs and supporting files.  The project displayed conflicts.  I couldn't figure out how to resolve the conflicts, so I was forced to put everything back in its orginal folder location on my machine.  It's a dangerous situation that we can't smoothly relocate nor rename OOP VIs, files, and folders.  NI needs to test and debug all common code maintenance maneuvers with OOP.

 

I could probably fix my problems by reconstructing all my classes and their VIs, but that is a huge amount of work for what I've built.  For this project, it looks like I'll have to stick with only accessing object elements using the Property Node.

 

Joe, I was able to fix my issue by re-creating the single VI that was not working properly. Thankfully I have only seen this issue on one occasion, but now several others have also reported very similar problems. This is not a very satisfying situation where you no longer have faith that the code is actually going to do what you tell it to do... 

Link to comment

I can see one other potential problem that might happen with the bundle but not the property node version: you've unbundled a reference and called a property node with that reference. Now, if for some reason that property node hits an error then the reference out from the property node might be set to Not a Refnum and the error cluster will contain the error information. If you use the bundle node then you bundle the Not a Refnum back into the class data without any checking at all - probably generating downwire bugs. With the property node accessor vi, the presence of the error in the error cluster will stop the Not a Refnum from getting put back into the class and chances are that other things will continue to work ok.

 

Of course this would mean that the caller of this routine wasn't checking the error out cluster, or possibly that the accessor proptery node vi was discarding an error - which would otherwise have picked up the problem.

Link to comment
Should I have kept out from the child class cluster all the elements of the parent class cluster?

Yes.

 

If the parent class contains the value in its cluster, the child class already has that value in its cluster, but you cannot access it through the bundle/unbundle nodes... it is private to the parent and the parent must expose a VI to let children access that value. 

 

What you should do is add two protected scope VIs to the parent class to do Read and Write of the value -- those two VIs should NOT be dynamic dispatch.

 

The elements in a child's private data control ADD to the elements in the parent's private data control. If you miss this point, you will have many bugs throughout your LVOOP code.

Link to comment
If the parent class contains the value in its cluster, the child class already has that value in its cluster, but you cannot access it through the bundle/unbundle nodes... it is private to the parent and the parent must expose a VI to let children access that value. 

 

What you should do is add two protected scope VIs to the parent class to do Read and Write of the value -- those two VIs should NOT be dynamic dispatch.

 

The elements in a child's private data control ADD to the elements in the parent's private data control. If you miss this point, you will have many bugs throughout your LVOOP code.

 

Wow, thank you for posting!  I screwed up.  I mistakenly thought that a child class's control cluster should have all of its parent class's elements plus its own specific elements.  Also, it's interesting to learn that a parent's elements cannot be accessed by a child method using bundle/unbundle.  I will edit the code and hopefully heal all without corrupting things.

 

The only thing I did right was making the property accessor VIs NOT dynamic dispatch even though the method VIs are all dynamic dispatch.

 

Request: a broken arrow, warning, or run-time error if a child class cluster contains an element of the same name as an element in the parent class.

Link to comment

Regarding your request: no can do because that isn't an error. A child class has no idea what fields its parent has. All the child knows is the API the parent exposes. How the parent chooses to implement that API is its business. The child might have its own functionality and decide to name a field with some name, and if that name overlaps, it doesn't matter ... the one that is accessed is specific to the context of the bundle/unbundle node.

When writing a child, pretend you know NOTHING about the parent other than the public and protected member VIs connector pane and documentation.

Link to comment
Regarding your request: no can do because that isn't an error. A child class has no idea what fields its parent has. All the child knows is the API the parent exposes. How the parent chooses to implement that API is its business. The child might have its own functionality and decide to name a field with some name, and if that name overlaps, it doesn't matter ... the one that is accessed is specific to the context of the bundle/unbundle node.

 

Well, something did malfunction as I illustrated in my earlier posts.  At first, I was able to pass the element named nPixels from one dynamically-dispatched child method to another method using bundle/unbundle.  This must have accessed the child's cluster element of that name, and as you say if the name overlaps a parent element, it doesn't matter.  But then when I made the parent's nPixels element accessible via Property node, the child's bundle/unbundle ceased to function correctly.

 

But as mentioned, when I attempted to duplicate this behavior in a new simpler project (with the same erroneous duplication of parent/child cluster elements) I could not recreate the problem.

 

Anyway, I'll avoid duplicating parent's element names in children clusters from here on.

Link to comment

Ok, now I'm a little confused...

 

What you should do is add two protected scope VIs to the parent class to do Read and Write of the value -- those two VIs should NOT be dynamic dispatch.

 

I generally do make my property accessor's dynamic dispatch in case in a child class I want to do some extra validation or data munging before I read or write the data for that child instance. Since I'm generally not organised enough to know when I design the parent class what I'm going to put in the child class, I've tended to stick to dynamic dispatch on a precautionary principle. Am I committing some utterly heinous OOP crime in ignorance ?

 

For similar reasons, I try to avoid using bundle/unbundle nodes for any element of the parent's data that I think I might end up wanting to hook extra validation or munging in a child class, even when I'm in a parent method.

 

A semi-concrete example of where I use this: I have a parent class that has a wavefcorm as part of it's private data. At various points in the child classes I want to check for and store in the child data specific waveform attributes, or to ensure that those attributes are eadded to the waveform. In these cases I overload the waveform accessor methods to handle the waveform attributes and add them to the child class's private data.

 

Of course in most cases the accessor vis don't end up being overloaded and I guess I pay a small overhead in the fact that I'm calling into a subvi rather than bundling/unbundling directly and possibly in the uncessary dynamic dispatch (although I though I understood that DD was not an expensive process when the method vi is not overloaded). Finally, I tend to make my accessors into property vis just because they take up less real-estate when I'm accessing a bunch of private data at a time.

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.