Jump to content

K-node

Members
  • Posts

    90
  • Joined

  • Last visited

  • Days Won

    1

Everything posted by K-node

  1. Hey Daklu, This thread has been great. I am starting to use AQ's Actor Framework with success on my systems. My derived classes add some features that probably break the proof of stability, but it is a risk that I accept. One of the latest things I did was to not propagate an error up into 'ActorCore.vi'. Once that happens, the Actor is dead. That is not why I am posting however. Your last two posts on Error handling, I think, deserve a thread of its own. Those coming into the top of this thread for the first time may never get to this gem of insight. I can start it if you want. -kugr
  2. Maybe I misunderstood the OP. I thought he wanted the name of the class and the names of its ancestor classes not the complete hierarchy of a class, that is, not including its children (descendants). He mentioned using a dynamic dispatch method, so this up the chain hierarchy would be determined at run time. Did I miss the objective here? Kurt
  3. I am not familiar with RT, but can't you use the Get LV Class Path vi and parse the name from that? Call your parent node vi and have it do the same thing? Each parent could append an array or append a string until you have a complete list? I can make an example if you need. Kurt
  4. Interesting challenge. I do not have a solution. From a different perspective, can you even do what you want with a arbitrary cluster? That is, go from a cluster directly to an array of variants. For a lame solution, the Read_All method has access to all of the class's private data. So you could just use the Unbundle method on the class's data, wire each element to the 'To Variant' method and build the array. Tedious, but perhaps better that calling all of the Read functions. Kurt
  5. Do your 'Run.vi's have a control on the front panel that *is* the parent object - like SciWare's Process.vi has an the object control in his ActiveObject framework? If so, can't you go get the value of that control and cast it to your desired object. This should be the instance of the object that launched the Run.vi, or am I missing something here. Alternately, each of your ActiveObject could keep a list of the Run.vi's it launched and then you could exhaustively search for the reference that matches in all of the ActiveObjects your app created. But I like my other idea better. Hope this helps.
  6. It is how I feel here at work. They have not appreciated the concept of OOP. Very nice suggestion. I added this approach to the project, the new vi is called: Main_ViaMultiUserEventRegEvents.vi. EventInClass_v2.zip
  7. OK, to polish my original post off and to help those that might be following along, I attached a project that shows 1) the problem (see Main.vi) where all the events have the same name and the event structure is tought to figure out what is what. 2) a solution as identified by mje (see Main_ViaTypeCast.vi) where we Type Cast the Object's event to an identical Event Refnum, but named differently. 3) a solution as identified by Jarrod S (see Main_ViaRefnumBundle.vi) where we bundle each of the Object's events into a previously created cluster with uniquely named events. 4) a solution also identified by Jarrod S (see Main_ViaRegistrationBundle.vi) where we bundle the Reg Events of each of the Object's events into a previously created cluster with uniquely named Reg Events. I hope that they are clear enough. Post here or PM me if you want. Anyway, I am liking #3 because I do not have to unbundle before I UnregisterForEvents. #2 has a similar feature, but as mje says, it is ugly. Also for you self proclaimed novices, explain to yourself why the EventCode value increments by 2 (as opposed to 1) for each button push. It is pretty obvious when you think about it, but, embarrassingly, it took me by surprise. It was a 'Well Duh' moment - I seem to have those way too often. Have a great weekend! -kugr EventInClass.zip
  8. I think this is what bean was referring to in http://lavag.org/top...n-event-refnum/. See post of May 13th where bean says: "Just make sure you only do one event per Event Registration Refnum when bundling the Event Registration Refnums into a cluster. I originally tried to group "sets" of events this way and revealed a bug. But, the way Ton has displayed will work since he just has 1 event (in this case, user event) per Event Registration Refnum." However this does not seem to be the bug of CAR 148149 (http://zone.ni.com/devzone/cda/tut/p/id/9996#148149_by_Date). Which deals with mapping event to case problems. I could not find anything in my quick scan of the 2009 SP1 known issues. -kugr
  9. In my case it is that the event structure that seems to get messed up. The frames have the right code. The event condition that they were originally associated with got switched or removed and replaced by an existing one. I am not sure what caused my remap. I originally thought it was because of the similar names. It may be related to this: http://lavag.org/top...dynamic-events/ At the moment, in my large app, I do have an Event Structure where an event is listed in multiple cases and I know I did not do that. I have not fixed it yet as the project is idle at the moment. I am OK with ugly if it is the prettiest work around. Thanks! -kugr
  10. This question was moved from the Application Design & Architecture forum ( ) as it extended the OT a bit much. So, I have created a Class (call it MyObj) that has refnum to an event held in its private data, the refnum is called MyEvent. The creation of the event uses a strict type def control (call it EventMessage). Each instance of MyObj will have its own event refnum, MyEvent. Here's the rub. Since the events are all created the same way, they have the same name (MyEvent). When I wire the event refnum into the Reg Events vi, I get a collection of the same named entries. Then when I try to handle these events in a Event Structure I get identically named cases (<MyEvent> : User Event), the only way I have been able tell them apart is to add them as cases in the order they were added to the Reg Events. On more than one occasion, the mapping (event instance to case) has gotten mixed up. There are some threads discussing this as well as a NI bug report. Is there a better way to do this? TIA -kugr
  11. I am going to move this question to the Object Oriented Programming forum. -kugr (edit: added link to topic)
  12. Ah, so that is how my remapping may have happened. I have a little different scenario. In my case, I have a Class (MyObject) that has a UserEvent refnum as a member of its private data. For each instance of MyObject, a UserEvent is created with a Strict Type Def Control named MyEvent. When I register events from multiple unique instances of these objects, the event names are all the same ("MyEvent"). I have been using the order that they were listed in the RegEvents method as I add them to Event Structure. I have had cases where it seemed they got messed up - and even if they didn't I get confused as to which event is from which object. Is there a better way to do this? Thanks kugr
  13. OK, Daklu, count me in. I wish these mid-level components were around months ago. I expect that I can give 4+ hours a week, perhaps more depending on how I can integrate the effort with my current projects. I have OO experience, so I can do some development, examples and documentation. Architecting is a possibility, but I am not good at UML type presentations. Is anyone going to NI Week? Perhaps it would be beneficial to meet. I have not made any arrangements - including begging for money from my management - but I might consider this. I would also have to see if I can grab some other resources (conference call, webex, etc.) if this is of interest - though that does not always work well with international schedules. -kugr
  14. LOL. I had some time (procrastinating on the documentation), so I was reviewing old posts. That's OK. It is not important. I'd rather press ahead on new problems. kugr
  15. OK, Daklu, time for some fun. How is your solution to this going? If I understand this correctly... SwitchBoxSettings_Initial = f(TestCase, TestDevice, TestPosition) SwitchBoxSettings_Changed = f(TestCase) and CommunicationPath = f(TestDevice, TestPosition) Is the SwitchBoxSettings_Changed also a function of SwitchBoxSettings_Initial and does it change over the duration of the TestCase? Would it need to notify a client that it is time for a change? I am leaning toward a SwitchBoxSetting class and probably a SwitchBoxSettingManager. Each SwitchBoxSetting instance would retain the trio that defines it along with all of the settings native to the SwitchBox. The SwitchBoxManager could return a SwitchBoxSetting for the trio of TestCase, TestDevice and TestPosition. It would run through it's internal collection of SwitchBoxSettings and return the one (or perhaps set) that qualifies. I have created my own ISerializable interface and SerializationInfo class that allows me to write the structure of a class to an XML file and later read it in. It would be possible to add new SwitchBoxSetting instances by editing the XML. You just have to know what the fields mean and the valid values. In my implementation, reconsituting the XML into LabView requires a 'factory' that can map class name to class instance. This eliminates the need to change any LV code if a new SBS is required or an existing one needs to be altered. Right now I am avoiding the issue of SBS_Changed. It can be implemented via a Manager approach, but I am not completely sure how it works.
  16. Thanks, Daklu. I have been lurking about, but have not posted. I have been immersed in my project which is heavily 'class data in a DVR' based. And I use interfaces, lots of interfaces, perhaps too many. It is very similar implementation to what you proposed some time back. I have not seen Jim Kring post is a bit either. He was a pretty early adopter of LVOOP. The project is essentially over - a prototype of sorts showing that we can do it if we need to. So it goes on the shelf for a bit while I write up an internal report on the implementation. There is very little knowledge on OOP for automation so part of the report is some fundamentals. I always liked your programming style and your justifications for your approach - I still do. I was disappointed that the additional ornaments on the VI icons were missing (remembering the cell phone and baby example). Because I am so focused on 'DVR the data', I would have DVR'd the data somewhere. My first thought was to do this in the Bag class. Then I thought again and I think I would have the DVR in the BagImplementation class. This would hide the Create and Destroy methods (needed to allocate the DVR and release it) from the user of Bag. This also means that BagImplementation needs Dynamic Dispatch methods of Create and Destroy. They would be no-ops in general. In my project, I started on an idea of IMemberVarsDVR interface and that a factory that created a new instance of any class would attempt to cast the object to this interface and if successful would call the Create method. This was late in the project and was not worth the change. Anyway, I could see something similar working here. Not sure that is the right approach though. It would be very cool to also make this part of a largeĀ® framework. I am trying to take my group into the OOP realm and need to make things as easy as possible. I'd be willing to help out on this. We should probably start a separate thread. If others join in, that would be great. Kurt
  17. I am not sure that limitation exists, at least in how I implemented this concept. Yes, the DVR only 'encapsulates' the data, but one of the pieces of data is the sibling object. So inside Object A's method X, we dereference Object A's data getting its sibling object (Object B) and call its method X. As Felix encountered, LV will not allow me to actually put an object of its own type in its private data cluster (that would exist in your approach too *see edit). So, you need to have a parent object. It could be the LV Object, but then I would have to send it through the 'to more specific class' function. In my recursion, I created a parent object with method X supporting dynamic dispatch (and reentrant execution). Personally, I prefer the 'DVR the object' approach. The constant need to dereference made it to cumbersome. The only way to encapsulate was to add a wrapper layer and that was a non-starter. -Kurt edit: I think I am wrong about the need in your approach. The refnum is probably hiding the fact that the object is the same type. edit2: I thought again. You still need some parent object.
  18. You are really getting into this OO stuff. Very nice! I have implemented this approach and I will admit that performance was not a design constraint. However, I would think that the performance impact can be minimized based on the implementation. First, if you implement a <List> class where it itself has a DVR with the data, then the 'owning' class does not have to have the <List> object in its DVR. This eliminates one de-reference IPE. This assumes that you don't mind having a mix of DVR and non-DVR data in an object's private data cluster. For my basic <List> class is is basically a wrapper around LV's own Array. I have added the method call overhead for Add, Remove, etc. so there is that hit on performance. But if the <List> is really a collection of objects, then I can pass a 'target object' into the wrapper representing "Index Array" to perform the "Preserve Runtime Class" method and have the method return the entity in the list correctly cast. I can see a use for this even if "a)" was implemented. Locking access to the list would suspend other threads from either modifying or obtaining stale data. I am assuming that the checkout method would return the 'Array' and the checkin would accept it. I do not like this approach from the replication of code. And are you just wrapping the 'Array' methods? This does not seem to eliminate the performance lost there. I've got nothing. Keep up the questions and share your experiences. My implementations have worked for me, but I am currently a sole developer at least in LVOOP here. My background is in text based languages C/C++/C# and only re-started programming in LV last June (after a 20 year hiatus). -Kurt
  19. I prefer the data inside a DVR. As you noted, this does make for a very clean interface. I generally define a single strict type data as a "Strict Type Def." control. This thread, if you have not reviewed it yet, has some good information: http://lavag.org/top...iew-oop-by-ref/ LabVIEW is clever that way. I find it a pain to deal with the casting ("To More Specific Class"), but all of this can happen in a "Get Sibling" method or some such thing. Nuances of race conditions, etc. aside, I am not sure if one is more robust than the other. In my project, I used the inner DVR approach. Though this requires a 'Create' and 'Destroy' method which are just begging for some sort of automation via scripting, I still find the approach very clear especially when I actually get to use the class. -Kurt
  20. Lief, My quick take... In the getClass2Reference.vi method, you are returning a reference to a copy of the Class2 instance that Class1 maintains. For simplicity, I always assume that when a wire is branched, the data is copied. So in this case the copy does not share the same memory for Class2's member variables (aka private data), String1 and String2. If you had a setClass2Reference.vi method which accepted a reference and used the dereference value to set Class1's member variable it would work. That would be kind of a silly solution - not sure what value the DVR brought you. Some of us have made the member variables of a class a DVR. So, any copies from a branched wire will still point to the same data. Care should be taken with this approach and you will find lots of discussion on this topic in this forum. Others make the class itself a DVR. Again, branches would have identical DVRs so any dereference would get you to the same data. Hope this helps. -kg
  21. This is slightly off topic: This VI which came in my installation of LV2009 provides a solution to creating a GUID... C:\Program Files\National Instruments\LabVIEW 2009\resource\Framework\Providers\API\mxLvGenerateGuid.vi After writing my own quasi-unique method, I found this little gem (grrrr-r-r-r-r). It may also be in earlier versions of LV. Is there another VI already native to the LV Functions palette for creating a GUID? I looked at a few hits from searching the LAVA forums but did not see any reference. -kg
  22. Miha, Ah, I see what you are trying to do. I have never used this approach yet. To get close to what is there... I added the Open VI Reference function to my block diagram I right clicked on the type specifier node and selected Create Constant. I then right clicked on the newly created constant and selected Select VI Server Class. From that submenu selected Strictly Typed VIs. Listed in that was Generic Plugin.lvclass, this was not in my project, but I added one later and the constant turned red. Sorry, this sounds very non-technical, but perhaps it will get you farther. Kurt
  23. Mike5, This link will describe many of the design patterns... http://decibel.ni.co...t/docs/DOC-2875 In particular it has a zip file with an implementation of the factory method. While it does not create a static VI reference since a class is really not a VI, it uses the path of the class and converts it using the Get LV Class Default Value VI. This implementation is interesting because it does not load the desired class into memory until the Load By Enum VI is called (this VI is part of the project). There are alternate ways to get the Factory to understand what classes it can create rather than an enumeration. Perhaps it could have a registration method where some other VI tells it to add a class path to its list - creating something like a name-value pair (probably implmented as two arrays - one with name, the other with path). The name would be something your application would use to tell the Factory to create. The value would be the path to the class. Alternately, if memory does not concern you, you can give the Factory an instance (rather than a path) of the classes it creates. The Factory would simply return the entry in its list based on the name it used to look up. Remember that as a data flow language, the class the factory got out of its list is an independent copy (unless you start using data value references in the class's private data). More on the DVR when you get to that point - there was an earlier thread on that subject. I hope this helps. Kurt
  24. Ah, thanks. Now I see how it works. It seems I have some retrofitting to do in my project. For #1, I have implemented this approach and GetNames is no longer used. I removed the InterfaceBag class too actually. In the GetInterface method, since you are asking for an interface (ISleepable) and not the implementation (ISleepableBaby) you cannot do a direct comparison, I had to use a PRT. If successful, then the implementation (ISleepableBaby wired from PRT's object out value) is returned. For #2, I do not see how I would get the implementation given the interface without obtaining a list of concrete implementations to compare against (or an equivalent call to the Interfaceable object). The only entity that knows what it implements is the particular Interfaceable object. Maybe I missed something.
×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.