LAVA 1.0 Content
Members-
Posts
2,739 -
Joined
-
Last visited
-
Days Won
1
Content Type
Profiles
Forums
Downloads
Gallery
Everything posted by LAVA 1.0 Content
-
Isn't there enough pi(e) already?
-
Hi, I need to get the row index of an empty row in a tree control. The idea is to allow user to type in new information to the tree control when she/he click a cell in the tree. The problem is that even though there is a method Point to Row Column in tree control, the method doesn't return row index but row tag. Since there is no row tag on empty rows, the method doesn't return any row-related information on empty rows. The question is how can I find out the row index when user clicks on the tree control. jimi EDIT: I figured it out by myself. One can typecast tree control reference to MultiColumnListbox reference and then use the method Point to Row Column method from MultiColumnListbox. This may not be very future proof way but it works currently. Any ideas of how to do this without using this trick?
-
LVOOP static method VI related issues
LAVA 1.0 Content replied to Aristos Queue's topic in Object-Oriented Programming
What if I want to have an interface for my VI so that the VI wouldn't do this "coincidental automatic downcasting". Perhaps I need such an interface because I'm not certain if I can implement my VI so that coincidental automatic downcasting would work in later revisions of the VI. However the functionality of the VI would simply be setting a object private data member value and then passing the object out. Such a VI interface would be considered to use "coinsidental automatic downcasting", and the problem is, I cannot think of any good way of preventing it. So I cannot write a VI that would preserve it's interface. The only way I can think of avoiding the coinsidental automatic downcasting would be placing a case structure with constant selector. Doesn't sound like Zen of LabVIEW. What I'm trying to say is that I think there needs to be a "manual override" for the coinsidental automatic downcasting so that the developer could at development time specify if this automatic behaviour will be used for a specific output terminal. So perhaps if the output terminals would by default be automatically downcasting but you could turn this feature off and then manually specify if an output terminal would be not downcasting or downcasting. EDIT: If coincidental automatic downcasting can change the interface of the VI, then this interface should be recognized also by type specifying VI constants and call-by-reference-nodes. Currently this interface is ignored by these nodes. If you try to call your method dynamically, the node interface is different from what it is when your call is statically linked. -
LVOOP static method VI related issues
LAVA 1.0 Content posted a topic in Object-Oriented Programming
I encountered some LVOOP class static method VI related issues. I reported these issues to NI, however I want to report them to the community as well so that you are aware of the issues, should you encounter them. When a child class is passed to a static method of parent class, the method output is automatically casted to child class type under certain conditions; if the class wire from class input to output is continous, then output class is automatically casted to more specific in the calling VI block diagram. I like'd this behaviour first. I even expected LabVIEW to behave that way. However, I noticed today that there are some issues that make this behaviour a real problem. See the attached project. There are two classes 1 and 2. Class 1 has static methods A, B and Class 2 has a dynamic methods C and D. In Main VI.vi there are three examples: The output of Method A is not automatically typecasted although the class wire is continous because there is a disable diagram in the block diagram of A. This is a bug, I think. The output of Method B is automatically typecasted becasue the class wire in B is continous. Ok. A method interface should complitely define the behaviour of the method in OOP. This guarantees that the developer can at later time change the implementation of the method and this change will not break any VI using the method. This is in the very soul of OOP and guarantees the reusability. In LabVIEW this means that the method connector pane should complitely define how the method can be used. However this doesn't hold for static LabVIEW class methods. This can be seen in the third example. Method B2 represents some later implementation of method B. Although the interface of methods B and B2 are identical, changing the internal implementation of B to B2 has broken a wire in the calling VI. This I think is really a design flaw that should be addressed in the next major release of LabVIEW. The method D is broken because of disable diagram structure. A definite bug! About the third point. What I suggest is that the connector pane would complitely determine the behaviour of the VI. This means that there should be something similar to the dynamic dispatch terminal in static VIs. This terminal wouldn't affect dispatching but would determine if the output is automatically typecasted. Methods written in LabVIEW 8.20 should be automatically upgraded to use this new type of terminal so that every method, the output of which is typecasted in 8.20, would be upgraded to have these new terminals instead of standard terminals. One alternative is to rename the dynamic dispatch output to simply dynamic output. Such a dynamic output would require that any wire connected to it would be continous from a class input. For dynamic VIs this input must be dynamic for static inputs it can be any of the class inputs. The input should not change from case to case in case structures. Download File:post-4014-1169496645.zip -
As a few VIs tell more than a thousand words, I wrote a simple example of what I mean. Unzip the example and open the project. In examples folder there is a single example that represents the idea somehow. This is all very preliminary. All by-value classes should inherit from the "Value Class" and all by-reference classes should inherit from "Reference Class". There are two hierarcies. The by-value hierarchy is the one that the developer creates manually. This example hierarchy contains a File class as a parent class and TextFile class as a child class. The corresponding dual reference classes are File Reference and Text File Reference. The dual hierarchy should be made automatically by some scripting tool. As I don't have such tool yet, I wired it manually. Download File:post-4014-1169480015.zip
-
How to handle interchangable VIs
LAVA 1.0 Content replied to gustav's topic in Application Design & Architecture
Another possibility would be polymorphic VI's. If the interface is the same, you could use the equipment reference vs Path reference to get the write instance from the poly vi. If you have a shift register that you get your reference from you could initialize with path or Equipment reference depending on what VI's you want. When you do the build you have an option to not include unused VI's from the polymorphic VI. -
Thanks! I wrote the example as I knew there are not very good examples on using LVOOP classes dynamically. That's true, you got it right. If the file operations do not ship with build-in safety mechanism against concurrent access, then accessing the file in multiple places of your application simultaneously may be risky. To overcome this problem you need to implement the safety mechanism by your self. The easiest way to implement such a safety mechanism is to store the reference to a single element queue. When your code needs to access the file, it get's the reference from the queue. The queue becomes empty and therefore no other part in your application can get the reference simultaneously. Only until you return the reference to the queue, other parts of your application can get the file reference. I don't really understand what you mean by a reference to the class itself. When you say "class", do you mean a class or do you mean an object (a runtime instance of the class) instead. LabVIEW objects do not have references that are exposed to users (internally they do). Therefore you cannot get a reference to an object. In addition class private data control cannot refer to itself recursively. In Refactoring the ReferenceObject thread we have used the technique to store the private data of the class to a single element queue. This way the objects of the class act as if they were by-reference objects. However this means extra work as you may have noticed. I understand that you would like some easier way to overcome this problem. I haven't really thought of the issue since I posted my inheritance example to the Refactoring the ReferenceObject thread . Now that I think it, there is one other alternative, but it's not that nice either. I post my alternative implementation on this issue to the Refractoring the RefereceObject thread as it suits there better and it's not something you would do by yourself. EDIT: here is the link to the other thread: http://forums.lavag.org/index.php?showtopi...amp;#entry23148
-
I thought of an alternative for the community implementing the by-reference classes in LabVIEW. The idea is as follows. One can create a dual hierarchy to any by-value class hierarchy. The dual hierarchy is identical to the source by-value hierarchy in a sense that it has a dual version of every class in the by-value hierarchy. In addition it would have a dual for every method in the by-reference classes. The connector pane of the dual methods would differ from the source methods in that all class terminals would be replaced with the dual counterparts. As the private data member of the root class of the dual hierarchy one would have a single element queue reference of a LabVIEW object queue. The root class would have protected methods: Preview Object, Get Object and Set Object. These methods would give all the methods of the dual hierarchy an access to the object stored in the queue. The dual classes would use these methods to store and access an object of the by-value counterpart of the class. The methods of the dual classes (dual methods) would be implemented so that they get the by-value object couterpart from the queue using Get Object method, cast the returned by-value object to more specific, then call the by-value method counterpart and finally use Set Object to store the by-value object back to the queue. This sounds like a lot of work. However, principally one could write an automatic tool that would create the by-reference hierarchy for any by-value class hierarchy and update the hierarchy when ever the by-value hierarchy is changed. This way your actual classes wouldn't be contamined with the ugly by-ref stuff but you would still be able to use your classes in by-ref fashion. In addition you would have the alternative to use your classes in by-value fashion. Anybody interested in writing such a by-value class to by-reference class tool that would automatically generate a dual by-reference hierarchy for any by-value class hierarchy? If the tool would still keep the dual hierarchy up-to-date when ever the source hierarchy is modified, then the actual implementation of the by-reference classes would be totally hidden from the user. There are some problems I can see in this implementation. Dynamic VIs of the the source hierarchy should have Dynamic VI counterpart in the dual hierarchy where the dynamic input terminals should be replaced with the dual counterpart. This is obvious but the problem is what to do with class terminals in the source hierarchy methods that are not dynamic dispatch terminals. Or class terminals that are of an ancestor class type? Or class terminals that are not of any class type from the hierarchy being processed? Or terminals in wich a class type is in a cluster, an array, a queue or event reference or a combination thereof. I do not have an definite answer to this question.
-
I wrote you an example that uses LVOOP class plugins to access different kinds of data files. Our real system is somewhat more complicated. The plugins in the attached example are opened at run time and correct plugin is automatically selected based on the file extension. I wrote two plugins, one for text and a second for binary data files. The text plugin uses queue based reference and the binary files uses native LabVIEW file reference. Of course the text file could use native LabVIEW file reference but I thought the example is more educative if I use queue based reference in the other plugin and you John also mentioned that you'd like to use queue based references. Open the File.prj project file and take a look at the two examples within. Download File:post-4014-1169410820.zip
-
Hi John, I'm not exactly certain what were you trying to do. However I try to answer your questions anyhow, tell me if I answered the wrong question. We are creating LVOOP objects dynamically. Our objects refer to files. As each file can be of different format, we need to have a file parent class and number of child classes, one for each file format. We have a factory class, which has a open file method. This method is passed a file path. From the extension of the file, the method identifies which file format is needed and calls appropriate file object constant returning VI dynamically (in a similar way as in your first example VI). This VI returns a parent class (File Class) constant. Then we pass this constant to a dynamic constructor VI with the file path as a parameter (dynamic meaning dynamically dispatched, but not called by-reference-node). The runtime type of the file class wire determines wich constructor should be called (dynamic dispatching). Then this constructor for the specific file type opens the file and stores file reference as a private data member. We have multiple "abstract" dynamic methods in the File Class to manipulate the file. These methods are then implemented in each file format class inheriting from File Class. We also have a dynamic close method, that closes all the references that have been opened. We only store file reference as private data so our objects act as by-reference objects. I understood that you want similar kind of behaviour but you do not have real references to store to private data members. You can overcome this problem by creating a queue in the dynamically dispatched constructor and storing what ever private data members to this queue. Then in each interface method of your child class you must get the data members from this queue, modify them and return them to the queue. In the close method you must empty the queue, properly close any references that has been stored to the queue (if any) and close the queue reference.
-
I agree with Jim. Perhaps even better possibility for the future would be a special XNode Wiki where registered LAVA users could describe their finding on XNodes. Investigating some .xnode XML files gave me the following information. XNodes are XML project files that can contain any number of files. What's special of XNode project files is that XNodes can contain special Ability VIs that control the behaviour of the XNode. The following code in the .xnode XML file specifies an Ability VI. The NI.XItem.Name property is mandatory for all Ability VIs and it specifies which ability is in question. NI.XItem.Type property is present for only some of the ability VIs and I don't currently know it's meaning. The VI_name can be arbitrary. Ability VIs can also be controls, at least State ability is always control and propably defines the format of XNode internal state. <Item Name="VI_name.vi" Type="Ability VI" URL="/path/to/VI_name.vi"> <Property Name="NI.XItem.Name" Type="Str">AbilityName</Property> <Property Name="NI.XItem.Type" Type="Int">0</Property> </Item> At least the following values are valid for the NI.XItem.Name property. State, AdaptToInputs, Bounds, CanAcceptDataDrag, DataDrag, DoubleClick, GenerateCode, GetDataForDrag, GrowInfo, Image, Initialize, ListErrors, Size, Terms, Compare, DisplayName, Message, UpdateState, Help, RefeeChanged, AutotoolRegions, BuildMenu, SelectMenu, OperateClick I browsed trough the LabVIEW.exe file (LV 8.0) with a hex editor, here are some findings. Many of the Ability VIs have an output terminal called "Reply". You can return information from the Ability VI using this terminal. The returned information is called "xreply". One can return zero or more xreplys. Possible values for an xreply are at least: UpdateTerms, UpdateImageAndBounds, ShowMenu, GenerateCode, ChangeTransactionName. Also the following values may be valid: UpdateLabel, UpdateImage, UpdateHelp, UpdateAutotoolRegions, ShowMenu, FailTransaction, ChangeTransactionName, PreserveUserCodeGUID. EDIT: Next Steps I think that the following things need to be clarified somehow. To create a ZIP file with all the ability VIs with correct front panel and connector pane To create an XNode with all of the abilities Figuring out what each ability does and when each ability is called by LabVIEW Figuring out the meaning of each xreply EDIT 2: To make reverse engineering a little easier, just take a look at the block diagrams of the Ability VIs in the following directory. For some reason they are not password protected in LV 8.0.1 LabVIEW 8.0\vi.lib\Platform\TimedLoop\XDataNode EDIT 3: To make things even more easy... open the following file in LabVIEW 8.0.1 "LabVIEW 8.0\vi.lib\Platform\TimedLoop\XDataNode\XDataNode.xnode" Right click XDataNode.xnode in LV project explorer and select "Save as" Select Copy and give a name for your own XNode Select a directory where you want to create your own XNode Start playing around... Note that even though the VIs are not password protected, there is a password in the .xnode file itself
-
Terrible Bug - While Loop Inside a Case Stmt
LAVA 1.0 Content replied to wwbrown's topic in LabVIEW Bugs
What I was trying to say is that if new general features affecting every VI will be introduced in every release, then there will never be a stable version of LabVIEW unless these new general features can be turned off. And Aristos was saying between the lines that optimization issues will be addressed in future version of LabVIEW. -
Terrible Bug - While Loop Inside a Case Stmt
LAVA 1.0 Content replied to wwbrown's topic in LabVIEW Bugs
The reason is that we developers can avoid using LVClasses if we knew they were buggy. We can avoid using notifiers if we knew they we buggy. But we cannot avoid optimization bugs if a specific buggy optimization cannot be turned off. In many other programming languages compilers are highly configurable so that developers can define which optimizations to use. In LabVIEW we only have debuggin on/off. And this is not a project specific option but a VI specific option. In many mainstream compilers there are different development versions and stable versions of the compiler. Development version may be more unstable but have more features. Stable versions then are very stable. In LabVIEW NI doesn't market new version of LabVIEW being unstable and old version being stable. Rather NI kind of gives an implicit promise that LabVIEW is a stable compiler regardless of the version. This however is not true. Because LabVIEW doesn't distringuish between stable and unstable version, some features may start getting stable but then there may be new features which make LabVIEW unstable again. Optimization bug is one such thing that can make a otherwise very stable compiler regarded as unstable. So if LabVIEW 8.20 would otherwise be considered stable compiler, forcing everybody to use new optimization feature, makes it unstable again. What I suggest is that every new feature, that cannot be avoided by simply not using it, can be switched off from LabVIEW options. This allows developers to choose between stable LabVIEW and feature rich LabVIEW. With new features I mean features that have a risk to be unstable or from which there is no experience yet. -
XNode trick by Aitor explained in this thread could propably be used to create template VIs that adapt to type.
-
I think that the most interesting possibility of XNodes is to be able to create template VIs that adapt to type, similar to those that robijn suggested in this thread.
-
Terrible Bug - While Loop Inside a Case Stmt
LAVA 1.0 Content replied to wwbrown's topic in LabVIEW Bugs
I agree. And I also would rather see no optimizations what so ever rather than miscomputing optimizations. -
Would you Aitor Solar like to post the VI in the above image to the forum, of course assuming it doesn't contain any stuff under NDA or something that would be illegal.
-
FYI, upgrading to 8.20 is MUCH more to loading your old code and recompiling. You'll have to create a project, check that your code doesn't suffer from LV bugs like the table problem, autoindexing/inplaceness, and then create a new installer (MUCH larger than in the past). If you haven't done this before, you may have a lot of work ahead of you....
-
There are also other options, which, I think, would be legal. The .xnode file is not itself copy protected (I think) but a plain text XML file. So the hard part is how to make the ability VIs (the VIs which control the behaviour of the XNode) and how to link the ability VIs so that they know they are part of the XNode library. - There is a XNode shipping with LabVIEW or some external package, the ability VIs of which have not been password protected. Then you could propably edit the ability VIs as the license is (techically) required only to create new ability VIs. - A. Solar has somehow been able to create ability VIs without needing to overcome technical copy protection.
-
Hello Aitor, same for me... here is what I get when I try to open youe xnode...
-
How do you manage to edit the XNode. When I open the .xnode file with my LabVIEW, a project explorer opens with a locked xnode in it. I think XNodes require a license, have you got one? Or is there an INI file setting that allows one to edit the XNode? Could you please write a short tutorial on how you created the XNode. jimi
-
"Figures don't lie, but liars figure"
-
Subversion, PushOk, LVDiff and LabView
LAVA 1.0 Content replied to scorpio's topic in Source Code Control
LabVIEW seems to modify multiple VIs when you edit one, especially in LabVOOP projects. Do you always need to check out the whole project, then modify one VI and finally check in the whole project. Or how do you guys do this with LabVIEW?