Jump to content

LabVIEW OOP By Ref?


Recommended Posts

Only been playing with 2009 for a few minutes or so...

Is this the by ref implementation of LVOOP?

Yes, a data value reference (DVR) to an LVOOP object supports lots of great features, such as:

  • use In Place Element Structure to get and operate on data, in place
  • works with To More Specific Class and To More Generic Class
  • DVR of Parent will coerce to DVR of Child
  • LVClass can be configured to only allow DRV creation of its object from within a member of the class

At JKI, we've been playing with this for a while and have worked out some cool design patterns that we're looking forward to sharing and discussing with the community, very soon (just need to fit this around NIWeek).

Link to comment

Yes, a data value reference (DVR) to an LVOOP object supports lots of great features, such as:

  • use In Place Element Structure to get and operate on data, in place
  • works with To More Specific Class and To More Generic Class
  • DVR of Parent will coerce to DVR of Child
  • LVClass can be configured to only allow DRV creation of its object from within a member of the class

At JKI, we've been playing with this for a while and have worked out some cool design patterns that we're looking forward to sharing and discussing with the community, very soon (just need to fit this around NIWeek).

Thanks Jim.

I missed out on the Beta Testing and this is all new to me.

And it's very exciting stuff thats for sure.

I have just been checking out Christian's Stuff (from this post), which looks awesome and is a great read.

AQ was correct in saying that LVOOP is used a lot in 2009 - even the new plot controls are LVOOP.

As you must know there seem to be alot of LVOOP additions - stuff thats I have seen been mentioned on LAVA is in there too (Friend Classes).

Since you have been using the DVR LVOOP objects for a while are you able to comment about what you have found on their implementation compared to ByRef GOOP toolkits (e.g. Sciware, Endevo, DqGOOP, OpenG etc..)?

Cheers!

Link to comment
The bottom line is that if you do by ref LVOOP this way, you're going with the grain and you'll find things to be much easier now and in the future as more native features and usability improvements get added to DVR+LVOOP.

Well put.

AQ was correct in saying that LVOOP is used a lot in 2009 - even the new plot controls are LVOOP.

That's a good point. You don't *need* to know LVOOP to use these new features, but if you've been waiting to get into the LVOOP world, now's a great time to dip your toes in the water...

Link to comment

That's a good point. You don't *need* to know LVOOP to use these new features, but if you've been waiting to get into the LVOOP world, now's a great time to dip your toes in the water...

I recommend everyone getting into it - as now I don't think I would want to code an app without it.

It was (and still is) a lot of fun to learn and program with.

The only issue I have is that my dev environment crashes alot (and I mean alot) when using it and I hoping this may have been fixed in 2009 (or occur less frequently).

In order to learn it I thought the best way was just to dive in head first :D do all the examples, read all the white papers, watch all the on demand videos and just start using it!

Around last year, I thought to myself that LVOOP was the way that NI had chosen to go with its OOP implementation so I decided I wanted to get into it and use it seriously for client apps.

At the time I was confident that LV8.5.1 was a very stable release for LVOOP - I had heard of some issues with its initial release around LV8.2.

We then moved up to LV8.6.1 internally and LVOOP had more features and improvements - which made it even better.

Its great to see once again that LVOOP has evolved a lot in 2009, and that it is starting to get used all over the place within LabVIEW.

So I am very confident that NI will continue to support it and will keep improving its implementation.

Along with all the new property additions to the .lvclass file - this addition of a native ByRef scheme (for any datatype in LabVIEW) looks awesome.

Plus NI have fixed up the conflicting file names get moved outside executable problem which usually comes up from using .lvclass files, (rather then .lvlib for me).

Therefore, from my point of view, I couldn't have asked for more in a release, from what I have seen: 2009 is a great release for me, as it covers my biggest issues/concerns/problems/gripes that I was facing as a LabVIEW developer using LVOOP on PC targets.

LVOOP moving to RT sounds sweet too.

Also wrt ByRef LVOOP - I can't wait to see the examples the community comes up with.

Cheers Kudos :beer_mug: to NI, (and of course AQ) for their brilliant work :thumbup1:

Edited by jgcode
  • Like 1
Link to comment

I've been playing some more with LVOOP 2009

I've been working on implementing active objects into the framework I posted earlier. An active object has its own process which is spawned when its instantiated. Active objects are useful if you want your object to have time dependent characteristics such as a pump controller. You can imagine that with an ordinary pump you can turn it on or off, but what about PumpVolume? You wouldn't want your PumpVolume method to hold execution while it turns the pump on, waits and then turns it off, instead a better way is if your PumpVolume method messaged to a process that handled this operation.

Attached is a demo that instantiates two pumps to demonstrate Active Objects and that each instance has its own process.

LVOOP2009_ActiveObj.zip

  • Like 1
Link to comment

Just keeping this thread alive.

I was wondering if anyone had any feedback on the LVOOP frameworks I was playing with, or had a different approach? I think there is a lot to explore here with DVR and LVOOP and I'd love to hear what everyone is doing. There is a lot of potential here that I think I have only just started to scratch the surface of.

Also are there any pitfalls with regards to storing the DVR of the data members as object data? It seems to work well, inheritance is fine and I can access the parent members if I want. Getting and setting the datamembers inside a method using the inplace structure works well also, but I want to check I'm not walking into something silly before I start using these frameworks in a project.

Link to comment
Just keeping this thread alive.

Please do!

Hey Kurt

I missed your posts on this thread so I have just downloaded your code. The code you posted is quite cool. And very similar to a current project I am working on - I have/had to model a furnace for a client and decided to go with an Active Object - the client runs from source (don't get me started) in LV8.2 so I couldn't use any licensed toolkits when hacking his system. But I basically used your Active Object from Endevo as the template with a LVOOP-SEQ framework and it is working really well. It seems that the DVR would slightly simplify this process.

I implemented the process.vi using the JKI State Machine which worked really well, so instead of having a finite State Machine, I had a queued State Machine that could except arguments using a syntax that I am familiar with. I used dynamic registration for the messages coming back. It worked nicely - so good job on the Endevo AO stuff. :beer_mug:

I actually have to give a user group presentation on this DVRs and stuff, so I have been playing with them all day today. They seem robust, I guess I have to keep using them to figure out how to do this stuff the best. But if anyone else can keep posting up what cool stuff they are doing with them that would be awesome.

One thing I did pick up - and correct me if I am wrong - it seems that the reference goes out of memory along with the owning VI. I had a launcher.vi that created the LVOOP-DVR refnum and then passed this to the launched VIs. By the reference seemed to die when the launcher stopped running. I don't have this issue with SEQs.

Link to comment

Please do!

Hey Kurt

I missed your posts on this thread so I have just downloaded your code. The code you posted is quite cool. And very similar to a current project I am working on - I have/had to model a furnace for a client and decided to go with an Active Object - the client runs from source (don't get me started) in LV8.2 so I couldn't use any licensed toolkits when hacking his system. But I basically used your Active Object from Endevo as the template with a LVOOP-SEQ framework and it is working really well. It seems that the DVR would slightly simplify this process.

I implemented the process.vi using the JKI State Machine which worked really well, so instead of having a finite State Machine, I had a queued State Machine that could except arguments using a syntax that I am familiar with. I used dynamic registration for the messages coming back. It worked nicely - so good job on the Endevo AO stuff. :beer_mug:

I actually have to give a user group presentation on this DVRs and stuff, so I have been playing with them all day today. They seem robust, I guess I have to keep using them to figure out how to do this stuff the best. But if anyone else can keep posting up what cool stuff they are doing with them that would be awesome.

Hi Jon

Cool, I'm glad you like it. Its basically the same philosophy that I put into the Endevo design pattern, DVR really does simplify the object management that had to be done with SEQ, but in the end as I understand it DVR is a SEQ at its core.

As I'm playing with it there is one thing I would really like, as with a queue you can preview the element, I'd like to see the same with DVR. At the moment all your methods have to employ a DVR Read/Write within an inplace structure. If I want a method that is just read only it will be locked until the current operating method completes, this is going to bog down a system that uses read only methods.

One thing I did pick up -and correct me if I am wrong - it seems that the reference goes out ofmemory along with the owning VI. I had a launcher.vi that created theLVOOP-DVR refnum and then passed this to the launched VIs. By thereference seemed to die when the launcher stopped running. I don't havethis issue with SEQs.

LabVIEW performs cleanup on any references that were created within a VI that is no longer executing. So you need a way to keep your Launcher in memory until all your spawned vi's are closed. Possibly What I would do is feed each Spawned VI a queue ref that they can use to message back to the launcher when they are closed. When all spawned vi's have been closed then you can close the launcher. Perhaps a rendezvous may also work.

The Endevo SEQ avoids cleanup when the caller is no longer executing is because I think you must be running in debug mode. In debug mode the object references are kept alive by a background process, as I understand it.

Link to comment

LabVIEW performs cleanup on any references that were created within a VI that is no longer executing. So you need a way to keep your Launcher in memory until all your spawned vi's are closed. Possibly What I would do is feed each Spawned VI a queue ref that they can use to message back to the launcher when they are closed. When all spawned vi's have been closed then you can close the launcher. Perhaps a rendezvous may also work.

The Endevo SEQ avoids cleanup when the caller is no longer executing is because I think you must be running in debug mode. In debug mode the object references are kept alive by a background process, as I understand it.

Cheers - The launcher is very easily solved by calling the UIs as subVIs and using dataflow (sequence structure) to keep everything alive.

post-10325-125052090582_thumb.png

Your request/issue for Read Only is inline with Jim's above. Maybe an idea for the exchange forum?

Also I think I found where this new subVI fits in - I used this badboy to recover the data and retain dynamic dispatching - nice!

post-10325-12505215389_thumb.png

Is there any other use cases for it?

Link to comment

one thing I would really like, as with a queue you can preview the element, I'd like to see the same with DVR.

I'm pretty sure that one of the main design goals for DVRs was to eliminate data copies caused by the feature. Forcing the user to have a read-write pair guarantees that at least (although the user can still cause copies inside the IPE structure). If we had the ability to read the value, a copy would have to be made. It might also require some additional mutexes, because presumably you don't want to read the value in the middle of the IPE structure changing it, but you also don't want to wait until it releases the lock.

P.S. That's not to say I object. At times I might accept read-only access (which would ideally not be affected by the lock) at the cost of an allocation. I don't know for sure that I would, though.

Link to comment

Your request/issue for Read Only is inline with Jim's above. Maybe an idea for the exchange forum?

Yes, I like Jim's idea, especially the unbundle concept so that you only make a copy of the element.

Also, it would be nice if you could wire a DVR LVOOP object into a Bundle by Name and Unbundle by Name and have LabVIEW automagically dereference/rereference the data behind the scenes. Right now, when you want to just get a value of an element of a DVR LVOOP object, you have to use an Unbundle by Name inside an In Place Element Structure. This is too much work for the programmer and makes the code look unnecessarily sloppy. The programmer's tendency will be to create a non-locking Get/Preview data method, but this isn't a great idea, because it makes a complete copy of the data -- by using an IPE Structure with an Unbundle by Name inside, you only copy the element.

I'm pretty sure that one of the main design goals for DVRs was to eliminate data copies caused by the feature. Forcing the user to have a read-write pair guarantees that at least (although the user can still cause copies inside the IPE structure). If we had the ability to read the value, a copy would have to be made. It might also require some additional mutexes, because presumably you don't want to read the value in the middle of the IPE structure changing it, but you also don't want to wait until it releases the lock.

P.S. That's not to say I object. At times I might accept read-only access (which would ideally not be affected by the lock) at the cost of an allocation. I don't know for sure that I would, though.

You are right, it would make a complete copy of the data, which isn't a great idea especially if you are just going to pick out one element from a cluster, but if Jim's idea were implemented it would make coding a bit simpler, and more efficient.

Perhaps all bundle and unbundle on an uninterrupted DVR wire are equivalent to R/W In Place.

Link to comment

I'm using Data Value References to my LVOOP objects and finding that one major pain point is that I can't dynamic dispatch using Data Value References. This results in me creating a lot of public byRef VI method wrappers to protected byVal methods in order to get the dynamic dispatching benefit of LVOOP.

I asked Stephen about this at NIWeek and he mentioned that the rationale for not allowing dynamic dispatching was going to be updated on the 'Decisions Behind the Deisgn' document -- but I couldn't find the rationale so I'm basically asking again here for public benefit. Is this a feature that could be implemented in the future or is there something fundamental that prevented this from being implemented?

Link to comment

I've been playing with 2009 today and I'm impressed, I love the ability to now build by ref objects using Data Value Reference and the in place DVR Read Write, this is brilliant.

I've been playing with an OOP framework and I've knocked up a simple demo. Have a play

LVOOP2009.zip

I looked at your example. My understanding of Object References is different. See Images.

post-2-12506341062_thumb.png

post-2-125063425577_thumb.png

One issue to resolve with this method is dynamic dispatching. It seems that you can't do dynamic dispatching using Data Value reference terminals. Hopefully this will be added in a future LabVIEW release. In the meantime you will probably have to do dynamic dispatching inside the In Place Element Structure.

  • Like 1
Link to comment

I looked at your example. My understanding of Object References is different. See Images.

post-2-12506341062_thumb.png

post-2-125063425577_thumb.png

One issue to resolve with this method is dynamic dispatching. It seems that you can't do dynamic dispatching using Data Value reference terminals. Hopefully this will be added in a future LabVIEW release. In the meantime you will probably have to do dynamic dispatching inside the In Place Element Structure.

I agree that the class should wrap a DVR to a cluster, but rather the DVR should wrap the class.

However, I'm not sure that I agree that we need dynamic dispatching of reference terminals. I think that I would prefer to be able to pass an object reference into a by value method and have LabVIEW automagically dereference and re-reference the object behind the scenes -- almost list wrapping the by value method in a IPE Structure on the block diagram of the caller that is using an object reference.

Link to comment

I looked at your example. My understanding of Object References is different. See Images.

post-2-12506341062_thumb.png

post-2-125063425577_thumb.png

One issue to resolve with this method is dynamic dispatching. It seems that you can't do dynamic dispatching using Data Value reference terminals. Hopefully this will be added in a future LabVIEW release. In the meantime you will probably have to do dynamic dispatching inside the In Place Element Structure.

Yeah, I saw something similar when I was looking around at how to implement by ref objects using the DVR, I took a look at the xCE code from NI that Jon pointed to and saw that the way that by ref objects are achieved is by getting a ref to the object, but to achieve dynamic dispatch you have to wrap your methods in an in place structure and use DVR R/W on the object reference. It works, but it’s a lot of work to implement and what I don’t like is that you are requiring your layer above your object to manage that objects by reference capability, which as developers we intuitively don’t expect to have to do. I like my objects to manage their own by ref capability.

So I thought that if the class just holds the DVR of the datamembers then I get dynamic dispatch without any fuss and I have a reference to my datamembers giving in effect a object that has by ref characteristics.

I agree that the class should wrap a DVR to a cluster, but rather the DVR should wrap the class.

However, I'm not sure that I agree that we need dynamic dispatching of reference terminals. I think that I would prefer to be able to pass an object reference into a by value method and have LabVIEW automagically dereference and re-reference the object behind the scenes -- almost list wrapping the by value method in a IPE Structure on the block diagram of the caller that is using an object reference.

Yes, I like this idea.

Link to comment
One issue to resolve with this method is dynamic dispatching. It seems that you can't do dynamic dispatching using Data Value reference terminals. Hopefully this will be added in a future LabVIEW release. In the meantime you will probably have to do dynamic dispatching inside the In Place Element Structure.
There are no plans to add this in a future version. It was explicitly rejected as a possible feature during brainstorming... I posted about this in the beta forums, and I *think* I updated the Decisions Behind The Design to talk about this. (If I didn't, remind me to update it soon.)
Link to comment

almost list wrapping the by value method in a IPE Structure on the block diagram of the caller that is using an object reference.

"List wrapping?" I'm unfamiliar with that term. (I think I need to code up a parser to understand that sentence. smile.gif )

I *think* I updated the Decisions Behind The Design to talk about this. (If I didn't, remind me to update it soon.)

I don't see any discussion about this in the document. Is this reminder soon enough? wink.gif

BTW, the image in the section What is the purpose of the "LabVIEW Object" class? doesn't render correctly. The second frame is almost complete cut off.

Edited by Daklu
Link to comment

I agree that the class should wrap a DVR to a cluster, but rather the DVR should wrap the class.

However, I'm not sure that I agree that we need dynamic dispatching of reference terminals. I think that I would prefer to be able to pass an object reference into a by value method and have LabVIEW automagically dereference and re-reference the object behind the scenes -- almost list wrapping the by value method in a IPE Structure on the block diagram of the caller that is using an object reference.

I like this idea as well.

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.