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: 

what is right way to store pointer of Class-Object in Labview array?

Solved!
Go to solution

Hi,

 

I am trying to implement class like below in Labview.
Capture.PNG

 

Is it right way to create array of object-pointer, resize array while run time, fill up array with object-pointer, and delete all object-pointer from array in Labview? 

 

Capture.PNG

 

Fill up Channel Class object pointer in Array. (In other word Create Constructor)
Capture.PNG

 

object pointer delete from Array. (In other word Create destructor)Capture.PNG

 

 

 

Download All
0 Kudos
Message 1 of 10
(3,592 Views)
Solution
Accepted by topic author Y@sh001

LabVIEW OOP objects are passed 'by-value'.

 

In your code snippets objects are being created and destroyed. Similarly creating wire branches creates copies of objects (not pointers to objects).

 

You can find many threads talking about whether this is a good thing. It is certainly an active decision by LabVIEW R&D to handle objects in this manner. Personally I think it is the right decision - it fits the LabVIEW dataflow paradigm. 

 

You can find 3rd party add-ons which handle objects by reference in LabVIEW (for instance GOOP) but I don't really have much experience with them.

 

There are also features like data value references (DVRs) (used by the toolkits) which can achieve the functionality you are looking for. I would say, in my opinion, there are only a few use-cases where this approach is necessary or desirable and it is more likely that you can handle things by value.

Nick
Message 2 of 10
(3,551 Views)
Solution
Accepted by topic author Y@sh001

@niNickC wrote:

 

Personally I think it is the right decision - it fits the LabVIEW dataflow paradigm. 

 

You can find 3rd party add-ons which handle objects by reference in LabVIEW (for instance GOOP) but I don't really have much experience with them.


I concur.

 

The way you're doing it now seems spot on. But it's not storing pointers, but storing the actual objects.

 

By ref would make (a little) sense here iff (if and only if) you where to change these channels outside the device, while the device has continuous access to them and the changes. To me, that seems like a terrible idea, for others (apparently) that's like heaven... In such a situation, I'd either keep copies of the objects inside the device, and make a method so I can update them at a time of my choosing (in an event for instance). A bit more work, but much better control over things, IMHO.

 

 

By reference can be achieved by making by reference objects (e.g. objects keeping data in DVR), but also by putting the objects in a DVR (DVR containing normal objects). To me, that is a bit more transparent (because non of my objects are by reference), as the DVR isn't "hidden". This could be wrapped in a "channels" class\object, keeping the channel objects "pure".

 

As a last remark, to me DVRs are a pain to debug. If the main VI stops running, the DVR is killed. I think some of those toolkits use a broker to make them persist (at the cost of potential memory leaks tough). But still one of the reasons I shy away from most things "by reference".

Message 3 of 10
(3,546 Views)

Thank niNIckC clarification about LV Object passing By Value and By Ref.

0 Kudos
Message 4 of 10
(3,524 Views)

Thank you   for giving me right direction in Labview coding.

"

By ref would make (a little) sense here iff (if and only if) you where to change these channels outside the device, while the device has continuous access to them and the changes. To me, that seems like a terrible idea, for others (apparently) that's like heaven... 

 

No, I am not handling channels array out side the Instruments class.

So that, I think I need to keep object by value inside Instruments Class. (That's means currently posted approach is Right. am I right?) 

 

"

In such a situation, I'd either keep copies of the objects inside the device, and make a method so I can update them at a time of my choosing (in an event for instance). A bit more work, but much better control over things, IMHO.

 

"

As per my understating I need to handle the Channel Object like below.   

Capture.PNG

 

GetChannleHandler.vi

Capture.PNG

 

Could you give more detail  on "(in an event for instance)." ?  Do I need to create any User event in Instrument class, and call the method for updating the Channel Object?

 

 

0 Kudos
Message 5 of 10
(3,518 Views)

Y@sh001 wrote: 

No, I am not handling channels array out side the Instruments class.

So that, I think I need to keep object by value inside Instruments Class. (That's means currently posted approach is Right. am I right?) 


Structurally, what you do is how I would do it.

 

The first thing I do is fill in the icon. If I don't, it drives me insane very fast. Showing the labels takes too much screen resources for me. Curiously, before I started OO, I didn't have much problems with that...

 

Some for the class library icon. It's the first thing I set. Especially when there's inheritance, it's essential for me.

 


Y@sh001 wrote:

 

As per my understating I need to handle the Channel Object like below.   

Capture.PNG

 

 

 

 


That is a good option. The alternative would be to let the device turn on\off channels, and return the Channel status(us). In one or two methods. That could get old when there is a lot you want to do with those channels. Each thing would need a method in the channel and the device. But still a good option.

 


Y@sh001 wrote:

Could you give more detail  on "(in an event for instance)." ?  Do I need to create any User event in Instrument class, and call the method for updating the Channel Object?


Well, that shifts the discussion towards architecture.

 

Let's say the user wants to turn off a channel. when that happened, an event would be triggered. Probably a normal value signaling event at first (pressing an 'apply' or 'OK' button). That could indeed trigger a user event, or signal a message in a producer\consumer or (Q)MH structure. It doesn't really matter.

 

When working with by reference objects, you could just change the channel(s) right there and then. As the references change, the device (perhaps running in a different loop) will automatically get the changes, and your done. The problem with this is that you could get race conditions. For instance while the code is halfway changing the channels, the device loop could be using the halfway result. This usually will be solved with some kind of interlocking mechanism. But to me, it's weird that you'd chose by reference for the benefit of concurrent access to objects, and then have to work on boilerplate code to prevent concurrent access.

 

But back to by wire... So for instance a dialog setting is changed by a user. Some sort of event (queue, user event, notifier, whatever) is send. This is handled somewhere\somehow by the device loop, and it will be able to handle the entire event in one go, if that is the desired effect. 

 

So you now have a method GetChannleHandler.vi.. I'd call it "Get Channel.vi". The object is a channel, and you're getting it. I get that "Handler" feels intuitive, but it's unnecessary. Less is more. I like to use spaces, because... why not? This isn't C. But no need to go into flavors...

 

In the 'event', set the channels in a "Set Channels.vi" (or just one in Set Channel.vi), and do appropriate updates to apply them. Either in the Set Channel(s) or in methods in the event, after setting the channels.

 

Of course the dialog would need to get the channels first. Those channels will originate from somewhere. So the dialog could get new channels from the same source, and then change them. Or, there could be a user event asking the device loop for the channel(s).

 

So, lots of options...

 

Message 6 of 10
(3,482 Views)

Hi   


Structurally, what you do is how I would do it.

"

Labview is totally new from. From Your opinion in First post,  I conclude that, I should use the object by Value. I was just verify with you, I am not doing any wrong, which is cost me more in future.

 

"

The first thing I do is fill in the icon. If I don't, it drives me insane very fast. Showing the labels takes too much screen resources for me. Curiously, before I started OO, I didn't have much problems with that...

 

Some for the class library icon. It's the first thing I set. Especially when there's inheritance, it's essential for me.

"

Thank you for give me guidance about more cleaner Labview Code.  I posted just testing code. But In future I will put with all edited Icon. 

 

"

Well, that shifts the discussion towards architecture.

 

Let's say the user wants to turn off a channel. when that happened, an event would be triggered. Probably a normal value signaling event at first (pressing an 'apply' or 'OK' button). That could indeed trigger a user event, or signal a message in a producer\consumer or (Q)MH structure. It doesn't really matter.

 

When working with by reference objects, you could just change the channel(s) right there and then. As the references change, the device (perhaps running in a different loop) will automatically get the changes, and your done. The problem with this is that you could get race conditions. For instance while the code is halfway changing the channels, the device loop could be using the halfway result. This usually will be solved with some kind of interlocking mechanism. But to me, it's weird that you'd chose by reference for the benefit of concurrent access to objects, and then have to work on boilerplate code to prevent concurrent access.

 

But back to by wire... So for instance a dialog setting is changed by a user. Some sort of event (queue, user event, notifier, whatever) is send. This is handled somewhere\somehow by the device loop, and it will be able to handle the entire event in one go, if that is the desired effect. 

 

So you now have a method GetChannleHandler.vi.. I'd call it "Get Channel.vi". The object is a channel, and you're getting it. I get that "Handler" feels intuitive, but it's unnecessary. Less is more. I like to use spaces, because... why not? This isn't C. But no need to go into flavors...

 

In the 'event', set the channels in a "Set Channels.vi" (or just one in Set Channel.vi), and do appropriate updates to apply them. Either in the Set Channel(s) or in methods in the event, after setting the channels.

 

Of course the dialog would need to get the channels first. Those channels will originate from somewhere. So the dialog could get new channels from the same source, and then change them. Or, there could be a user event asking the device loop for the channel(s).

 

"

Thank you for explaining detail on Event handler, race Condition, and naming convention of Vi. It help me to create more cleaner and efficient code.

I am very appreciate you for pointing my mistake in Labview Code.        
 
 

 


 

0 Kudos
Message 7 of 10
(3,455 Views)

wiebe@CARYA wrote:

When working with by reference objects, you could just change the channel(s) right there and then. As the references change, the device (perhaps running in a different loop) will automatically get the changes, and your done. The problem with this is that you could get race conditions. For instance while the code is halfway changing the channels, the device loop could be using the halfway result. This usually will be solved with some kind of interlocking mechanism. But to me, it's weird that you'd chose by reference for the benefit of concurrent access to objects, and then have to work on boilerplate code to prevent concurrent access.

 

 

 


DVRs take care of that for you. If your data is inside a DVR that data is automatically locked while you are interacting with it inside a DVR structure. Any other DVR structure trying to act on the same DVR will be blocked. The data is protected. You can still get issues with acting on the current data in one loop when it is being updated in another. However, that is true no matter what in an application with parallel tasks accessing the same data set. However, the really nasty race condition of encountered with a read-modify-write construct is eliminated when using a DVR.



Mark Yedinak
Certified LabVIEW Architect
LabVIEW Champion

"Does anyone know where the love of God goes when the waves turn the minutes to hours?"
Wreck of the Edmund Fitzgerald - Gordon Lightfoot
Message 8 of 10
(3,444 Views)

Y@sh001 wrote:


I am very appreciate you for pointing my mistake in Labview Code.        
 
 


Just to be picky, it is LabVIEW, not Labview. LabVIEW is actually an acronym which stands for Laboratory Virtual Instrument Engineering Workbench.



Mark Yedinak
Certified LabVIEW Architect
LabVIEW Champion

"Does anyone know where the love of God goes when the waves turn the minutes to hours?"
Wreck of the Edmund Fitzgerald - Gordon Lightfoot
Message 9 of 10
(3,440 Views)

@Mark_Yedinak wrote:

wiebe@CARYA wrote:

When working with by reference objects, you could just change the channel(s) right there and then. As the references change, the device (perhaps running in a different loop) will automatically get the changes, and your done. The problem with this is that you could get race conditions. For instance while the code is halfway changing the channels, the device loop could be using the halfway result. This usually will be solved with some kind of interlocking mechanism. But to me, it's weird that you'd chose by reference for the benefit of concurrent access to objects, and then have to work on boilerplate code to prevent concurrent access.

 

 

 


DVRs take care of that for you. If your data is inside a DVR that data is automatically locked while you are interacting with it inside a DVR structure. Any other DVR structure trying to act on the same DVR will be blocked. The data is protected. You can still get issues with acting on the current data in one loop when it is being updated in another. However, that is true no matter what in an application with parallel tasks accessing the same data set. However, the really nasty race condition of encountered with a read-modify-write construct is eliminated when using a DVR.


Only if everything is in one DVR, and if all change happen in one go.

 

If each channel has a DVR, changing them all in a separate loop could (will) result in unsynchronized updating in the other loop. Steps to avoid that need to be taken.

 

 

Message 10 of 10
(3,422 Views)