Jump to content

Trying OOP in Labview 8.2


Recommended Posts

I'm trying out the new OOP in LV 8.2. I see how the inheritance works in practical terms. Say I make Class1 a cluster with elements A and B, and I make Class2 a cluster with elements A, B, and C. Then I make Class2 inherit from Class1. Now I can wire a Class2 object wire to a Class1 'method' VI, and the method VI will work as long as I've used Unbundle/Bundle By Name inside. Essentially there is now a way to wire different clusters to the same subVI node without dealing with polymorphic VIs, and keep things organized with a classes and inheritance hierarchy. This is a very good new feature, I think.

The only way so far I can figure out to change the object's cluster elements is to make a method VI to handle it. Outside the method VI, I can't use an unbundle/bundle on the object wire. Also, I tried wiring it to the reference input of a Property Node. It connects without a broken wire. When I saw that, I thought 'wow' I'd be able to pull down a list of the cluster elements as the object's properties. But the list was empty. So, are method VIs the only way to change the cluster elements?

Now I see in the Labview Help: 'Class cannot be bundled or unbundled because the class private data is empty: You cannot bundle or unbundle any LabVIEW class that has no private data. A LabVIEW class need not include any elements in its private data cluster. But if the class has no private data elements, there is no need to attempt to bundle or unbundle those elements. To correct this error, you can add elements to the class private data or leave the class private data empty and choose an operation other than bundle or unbundle.'

My private data is a non-empty cluster, but I still get a broken wire when trying to bundle/unbundle. Maybe they are talking about only inside a method VI.

Link to comment

Wow you're fast,

but it is correct you cannot access data insade an object directly, you have to make a method for this.

On the NI forums there is a white paper about OO in LV 8.2, this is a very good explenation about the implementation in G. I think this white paper should be shipped with LabVIEW

Ton

Link to comment

So far I feel a little bit dissapointed with the new integrated version of GOOP. It's Lack of "Passing By Reference" takes away a lot of the area's where we tend to use objects. There is no real creation of an object and destroying of it. They really appear to be nothing more than a glorified Cluster that enforces some degree of good programming techniques. I'm not saying its all bad, I think its surely a move in the right direction. When I first heard about the OOP being integrated I thought that one of my first projects would be converting all my endevo objects over to LabVIEW objects, however after seeing the need for direct dataflow with no parallism (sp?) I see that this project is something thats going to have to wait until the next version of LabVIEWs GOOP that has "Passing by Reference".

Overall... Fairly dissapointed, but It's still good as far as showing progress in the right direction.

Time to get back to the next session!!!

Dave Graybeal

Link to comment
So far I feel a little bit dissapointed with the new integrated version of GOOP. It's Lack of "Passing By Reference" takes away a lot of the area's where we tend to use objects. There is no real creation of an object and destroying of it. They really appear to be nothing more than a glorified Cluster that enforces some degree of good programming techniques. I'm not saying its all bad, I think its surely a move in the right direction. When I first heard about the OOP being integrated I thought that one of my first projects would be converting all my endevo objects over to LabVIEW objects, however after seeing the need for direct dataflow with no parallism (sp?) I see that this project is something thats going to have to wait until the next version of LabVIEWs GOOP that has "Passing by Reference".

This was the exact reaction by myself and co-workers as well. In fact, someone even used the term "glorified Cluster". At first, being able to create classes from the project browser, inheritance, and and the ease of use looked promising. The lack for pass by reference and not being able to name instances is a big drawback. In fact, I'll be sticking with the Endevo stuff (disclaimer - my employer sells this toolkit in the US). I guess the current implementation is closer to the data flow paradigm. However, queues break this thought as well and is one of the most powerful features in LV.

NI, you were so close at getting GOOP right. At least LV8.2 loads faster.

Link to comment

I don't understand Dave and Toby's objections. From what I can figure out, the object wire behaves as a reference, so if you wire it in and out of VIs you are 'passing by reference.' You can create multiple objects of a class by making an array of objects, using the Initialize Array function or a For Loop with a class constant inside that you dragged from the project window. You can pass that array around via a global variable, an uninitialized shift register (LV2-style global), or wired. The object is destroyed when the wire ends, just like any other kind of data wire, so you don't need an explicit destroy function.

Regarding being able to name objects, I don't see the need. This is Labview, not a text language with text variable names. Naming has proven useful with Queues and the other synchronization functions because they're part of your program architecture and you don't use very many at once. And with the naming, you don't need to pass the queue reference around nor worry about who created the queue first. Objects, on the other hand, are data, a completely different animal. You might have thousands of objects of a class existing at once, in which case you don't want to name them, but you do want them in an array.

The only missed boat I see here is that it would have made sense to have the standard Property Node be able to read and write the cluster elements of the object. I don't think that would be hard for the LV developers to implement.

Link to comment
I don't understand Dave and Toby's objections. From what I can figure out, the object wire behaves as a reference

I'm pretty sure it's by-value, at least according to the white paper. If the wire forks and goes into two different sub-VIs, you've now got two copies of the original object.

The only missed boat I see here is that it would have made sense to have the standard Property Node be able to read and write the cluster elements of the object. I don't think that would be hard for the LV developers to implement.

Wouldn't that violate the whole point of data encapsulation? At that point, you might as well just use a cluster.

Link to comment
The only missed boat I see here is that it would have made sense to have the standard Property Node be able to read and write the cluster elements of the object. I don't think that would be hard for the LV developers to implement.
Wouldn't that violate the whole point of data encapsulation? At that point, you might as well just use a cluster.

No, I think it would be quite appropriate. That's why the Property Node is provided. It allows you to read and write the properties of an object, such as an ActiveX object, with the list of properties being specific to the object's class. The elements of a .lvclass object's control cluster are what we should think of as the object's properties.

By just using a standard cluster, you don't get the benefit of class inheritance with the automatic 'polymorphism' of method VIs when wiring superset clusters. That's a nice benefit.

Also, I'd like to see all the method VIs, and inherited method VIs, accessible with an Invoke Node with the object wired in as the node's reference input. Then it would feel more like I'm using an object rather than a kind of polymorphic VI.

Link to comment
Regarding being able to name objects, I don't see the need. This is Labview, not a text language with text variable names. Naming has proven useful with Queues and the other synchronization functions because they're part of your program architecture and you don't use very many at once. And with the naming, you don't need to pass the queue reference around nor worry about who created the queue first. Objects, on the other hand, are data, a completely different animal. You might have thousands of objects of a class existing at once, in which case you don't want to name them, but you do want them in an array.

You don't "need" to name queues either. In fact, I usually only do this to make the code more readable. But, the ability to do so makes them much more powerful. Also, queues are objects -- data, methods, encapsulation. Anyway, I don't want this to turn into a thesis on what makes queues wonderful. I do see the points of those who prefer the NI implementation. It makes objects as easy as any other data structure in LV. I wouldn't want to malloc each array either. It is just a personal preference, I guess. As Dave said, maybe the next version will have the features that some of us feel is missing.

Link to comment

As others have pointed out, so close ...

But instead of concentrating on what is still missing, I hope to see (and soon contribute) some examples of nifty things that people have been able to do with the new functionality.

I guess my reaction is the same as it was when shared variables came out. Initially, I and many others, said, "Its just a glorified global", but they have been quite useful, even if they are not everything we wanted them to be in the first incarnation. I'm sure we will see improvements and additions to the new OOP soon.

Til then, I'm still going to have fun with the new toys in 8.20 and Mindstorms as well.

Link to comment

Alright, well I almost feel a little guilty about being so quick with my first post. After giving the overall concept more thought and discussion ( had a great chance to talk to many of the LAVA Guru's at the Salt Lick about this implementation), I don't feel nearly as cheated in this new implementation. I see the reason that this version of GOOP was a great feature which was lacking which is the passing by value (dataflow). After some dialogue with a few folks, it really doesn't sound tremendously difficult to create some wrapper vi sets to use your objects with to create the by reference feel of other current GOOP toolkits.

I do hope that "passing by reference" is something that gets implemented natively in the next version or two, however I do see the advantages of having a truly by value object and the couple quick ways to use them in a non-natively "by reference" way.

Although I'm still not able to move all my objects over from my endevo build to a labVIEW native object, I'm glad they implemented what they did. It truly is a great step in the right direction.

Dave Graybeal

Link to comment

Alright, well I almost feel a little guilty about being so quick with my first post. After giving the overall concept more thought and discussion ( had a great chance to talk to many of the LAVA Guru's at the Salt Lick about this implementation), I don't feel nearly as cheated in this new implementation. I see the reason that this version of GOOP was a great feature which was lacking which is the passing by value (dataflow). After some dialogue with a few folks, it really doesn't sound tremendously difficult to create some wrapper vi sets to use your objects with to create the by reference feel of other current GOOP toolkits.

What techniques have you learned for wrapping by value GOOP to get a by reference "feel"? I have 10 openGOOP classes I need to rewrite using the new model but they rely on the by reference approach. Any referrals would be appreciated.

Link to comment
What techniques have you learned for wrapping by value GOOP to get a by reference "feel"?

One technique I've seen in general for using "by reference" semantics is to use a single element LV queue. The basic idea is you create a queue of length one, and everytime you want to use the data, you dequeue it with an infinite timeout (so in case someone else is using the element you wait until it is your turn) and then once you are done with the object, you enqueue it again. Unfortunately, this approach does create a lot of clutter on your diagram everytime you access your object, and if you're dealing with multiple objects, you have to be careful not to deadlock.

Link to comment
One technique I've seen in general for using "by reference" semantics is to use a single element LV queue. The basic idea is you create a queue of length one, and everytime you want to use the data, you dequeue it with an infinite timeout (so in case someone else is using the element you wait until it is your turn) and then once you are done with the object, you enqueue it again. Unfortunately, this approach does create a lot of clutter on your diagram everytime you access your object, and if you're dealing with multiple objects, you have to be careful not to deadlock.

This is one of the ways that I was thinking that could be used to give the by reference feel. Another that I think would work is if you use the endevo GOOP as a wrapper for the LVGOOP. Although it may seem a little redundent, I think it would give you a lot of flexibility for when by reference becomes implemented in the LV package. I believe you could probably ( not tested and only mildly thought about ) use the endevo GOOP package like normal, using the LV Object as your Data Member. Then in each of the methods you call the LV Native Methods for your object and pass in the Object Data Member. One thing that crosses my mind if this would work or not would be how LV actually protects its private and protected methods, so I'm not sure if that would cause any problems trying to implement.

I hope this helps!

Dave Graybeal

Link to comment

QUOTE

This is one of the ways that I was thinking that could be used to give the by reference feel. Another that I think would work is if you use the endevo GOOP as a wrapper for the LVGOOP. Although it may seem a little redundent, I think it would give you a lot of flexibility for when by reference becomes implemented in the LV package. I believe you could probably ( not tested and only mildly thought about ) use the endevo GOOP package like normal, using the LV Object as your Data Member. Then in each of the methods you call the LV Native Methods for your object and pass in the Object Data Member. One thing that crosses my mind if this would work or not would be how LV actually protects its private and protected methods, so I'm not sure if that would cause any problems trying to implement.

Thanks! My thoughts have been along the same lines. I am using dqGOOP which is LV queue based using clusters. As long as you can enqueue and dequeue a class instance, I should be good to go. I hope the extra method call required to access the LVGOOP class data does not add too much overhead. :D

Link to comment
One technique I've seen in general for using "by reference" semantics is to use a single element LV queue. The basic idea is you create a queue of length one, and everytime you want to use the data, you dequeue it with an infinite timeout (so in case someone else is using the element you wait until it is your turn) and then once you are done with the object, you enqueue it again. Unfortunately, this approach does create a lot of clutter on your diagram everytime you access your object, and if you're dealing with multiple objects, you have to be careful not to deadlock.
Link to comment
One technique I've seen in general for using "by reference" semantics is to use a single element LV queue. The basic idea is you create a queue of length one, and everytime you want to use the data, you dequeue it with an infinite timeout (so in case someone else is using the element you wait until it is your turn) and then once you are done with the object, you enqueue it again. Unfortunately, this approach does create a lot of clutter on your diagram everytime you access your object, and if you're dealing with multiple objects, you have to be careful not to deadlock.

Yes and the name of that technique is dqGOOP and all of that "clutter" is taken care of with wrapper VIs.

Here are some links:

dqGOOP Toolkit Order Page

dqGOOP Online Help

Don't worry, I will be looking how to integrate dqGOOP with 8.20 as I'm sure the other GOOP framework providers are as well!

FYI, be on the look out for a new* inheritance proposal for GOOP (not just dqGOOP but I believe that I have a technique to add inheritance using dqGOOP, openGOOP or the old free NIGOOP). Unfortunately, I will be out of the office for this upcoming week so I will not be able to look at 8.20 at least until the following week.

*This is not the current inheritance proposal using a queue with flattened data.

Brian

Link to comment
Yes and the name of that technique is dqGOOP and all of that "clutter" is taken care of with wrapper VIs.

Brian

The way I see it, the 8.2 class becomes a subclass of the dqGOOP class. One implementation is the 8.2 class (itself a cluster) is the only component of the dqGOOP class data cluster. Then the dqGOOP wrapper VIs (the methods) are used to call the 8.2 class methods to access the data. Inheritance and automatic dispatching come with the 8.2 model so one of the few remaining issues is efficiency. Another issue is how to dynamically create the 8.2 class in the first place, though I think this is addressed in a recent NI white paper (attached).

I'll see if I can run some benchmarks with the above versus standard dqGOOP. Whatever penalty might be worth the hit to capitalize on future OOP enhancements coming from NI.

W. Brown

Download File:post-4503-1155396456.doc

Link to comment
This is one of the ways that I was thinking that could be used to give the by reference feel. Another that I think would work is if you use the endevo GOOP as a wrapper for the LVGOOP. Although it may seem a little redundent, I think it would give you a lot of flexibility for when by reference becomes implemented in the LV package. I believe you could probably ( not tested and only mildly thought about ) use the endevo GOOP package like normal, using the LV Object as your Data Member. Then in each of the methods you call the LV Native Methods for your object and pass in the Object Data Member. One thing that crosses my mind if this would work or not would be how LV actually protects its private and protected methods, so I'm not sure if that would cause any problems trying to implement.

I hope this helps!

Dave Graybeal

I think you've hit the nail on the head. I think the "pass by reference" issue really is one that should have received attention in the last couple years, because you get some real performance problems when you pass a large data structure between stages of a VI just to get it from VI #1 to VI #7. The workaround is probably to dump it in a global, but now you are really enforcing bad coding style. So hence, my reaction last week about NI managing to implement GOOP before "pass by reference" is a landmark in language devolution.

Still, I think we can all see the continued march of G as a very serious development language and platform, rather than a simple prototyping tool.

Link to comment

Regarding passing-by-reference vs. passing-by-value when wiring data into and out of a subVI: I would like to see that handled by the Labview engine behind the scenes. One great thing about Labview is that it's a very high level language, and the programmer doesn't need to be concerned with a lot of low-level junk, because in many cases we're physicists number one and programmers number two. Greg McKaskle indicated in his posts years ago that in specific past versions of Labview, there was some intelligence regarding passing data to subVIs, and in some cases Labview would NOT make another copy of the data when it's wired into a subVI. So, at least in the past, Labview was able to intelligently decide whether to pass by value (make a new copy) or pass by reference (keep the data just in its one place in memory), based on forking and parallelism and based on whether the data is modified or just read.

Link to comment
The only missed boat I see here is that it would have made sense to have the standard Property Node be able to read and write the cluster elements of the object. I don't think that would be hard for the LV developers to implement.

The cluster elements are accessed through bundle/unbundle on the diagrams of member VIs.

When exposed outside of the class, we require you to go through member VIs (for a variety of reasons). At one point, we were going to allow member VIs with a specific conpane to be accessed through the Property Node (that's why the property node allows you to wire to it). Alas, this was dropped for lack of priority. It is "syntactic sugar" -- it makes it a bit easier to set a batch of properties, but wasn't required for the release since you can just drop all the subVIs. It would not surprise me if a future version picks that feature up, but, standard R&D caveat, no promises. ;-)

Link to comment
By just using a standard cluster, you don't get the benefit of class inheritance with the automatic 'polymorphism' of method VIs when wiring superset clusters. That's a nice benefit.

LabVIEW classes aren't exactly standard clusters. For one thing, the method VIs *do* get the benefit of automatic polymorphism. Suppose you have a subVI that takes a Parent class in and gives a Parent class out, and on the block diagram the input connects to the output (possibly passing through other nodes along the way). We do a syntactic analysis of the subVI's diagram to prove that the runtime type is going to be maintained from start to finish. If the subVI's diagram passes that analysis, then when you drop that subVI and wire a Child class to it, the output will automatically downcast to a Child class.

Also, I'd like to see all the method VIs, and inherited method VIs, accessible with an Invoke Node with the object wired in as the node's reference input. Then it would feel more like I'm using an object rather than a kind of polymorphic VI.

Why is there no emoticon for sobbing?

The Invoke Node would make you "feel more like I'm using an object"?! This makes me really wish that we'd had OO before VI Server. VI Server has conditioned everyone all wrong. The Invoke Node is identical to a subVI call... only it doesn't have an icon so it isn't understandable across human languages, and it doesn't have a conpane, so inputs and outputs are just stacked arbitrarily. The Property Node actually adds some useful syntax (stacking multiple function calls together). The Inovke Node just puts a big ugly text block on your diagram instead of an elegant subVI node. Please don't ask for support for the Invoke Node... I'm not sure I could write code through the tears.

Link to comment
Why is there no emoticon for sobbing?

The Invoke Node would make you "feel more like I'm using an object"?! This makes me really wish that we'd had OO before VI Server. VI Server has conditioned everyone all wrong. The Invoke Node is identical to a subVI call... only it doesn't have an icon so it isn't understandable across human languages, and it doesn't have a conpane, so inputs and outputs are just stacked arbitrarily. The Property Node actually adds some useful syntax (stacking multiple function calls together). The Inovke Node just puts a big ugly text block on your diagram instead of an elegant subVI node. Please don't ask for support for the Invoke Node... I'm not sure I could write code through the tears.

Stephen, I believe that in this case Joe refered more to the option of being able to wire a reference into a node and having that reference determine which options are available to you. This makes it easier than having to find the right palette and VI. This is somewhat helped by the context menu options which let you see the relevant palettes when you click a wire of a certain type, but selecting a method or a property is still technically easier even if the node itself is uglier.

BTW, I'm sure if you PM Michael A. he'll put you in the NI group. The more NI R&D guys (and gals) we have over here, the better, and it's nice for them to be easily recognizable.

Link to comment
The Inovke Node just puts a big ugly text block on your diagram instead of an elegant subVI node. Please don't ask for support for the Invoke Node... I'm not sure I could write code through the tears.

Wow, what a Labview purist you are. I like that! I've been coding Labview almost every day for 15 years and am much of a purist myself, especially in architecture style, use of a deep hierarchy of subVIs, and use of wires and shift registers instead of globals and locals. However, I've never made a pictorial VI icon! They only have tiny text in them over a pastel blue background. I see your point. But, for me, the Invoke Node and Property Node for Labview objects would be convenient options to have, and wouldn't be too ugly. Here, I'll pass you a box of tissues.

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
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
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.