-
Posts
1,824 -
Joined
-
Last visited
-
Days Won
83
Content Type
Profiles
Forums
Downloads
Gallery
Everything posted by Daklu
-
Okie... try this. The palette is in User Library -> LavaCR. Code is in vi.lib\addons\_LavaCR\Tree Control API. (The original Library is in 8.2. I had to recompile to 8.6.) lava_lib_tree_control_api-1.0.1-1.vip
-
In that case, I have no idea.
-
The more important feature (for me) is the ability to set the scope for specific classes within the library. I can have all sorts of utility and worker classes in the library that I've scoped as private and aren't part of the library's public api. This ability alone is a huge help in keeping my code organized and maintainable.
-
Both. I don't remember that discussion. Does that mean all the classes in a library (and all class members) get loaded, or just the class members of the one class that is used (assuming multiple classes in a library?) I no longer have a general reuse library for simplish operations, primarily because the benefit I got from them didn't justify the overhead of maintaining them in a reuse library, but also because I'm trying to control the dependencies my applications and reuse code has on external modules. I do have a bunch of utility VIs I can use, but I'll either copy the vi and add it to the application code or occasionally I'll copy the code directly to my target vi. My reuse code modules target relatively large chunks of functionality, such as message handling, various kinds of data structures, etc. If I had released a single class as a reusable code module, and later wanted to extend the functionality with additional classes, I would create a new code module with the original class and the additional classes packaged in a lvlib. The original class and the class in the lvlib can exist in memory at the same time, so the calling code doesn't break. If I want to upgrade source code to the new library, then yes, code breaks and I have to fix it manually. However, so far the only single-class reusable code modules I have are instrument drivers and I haven't encountered a situation where I would add additional classes to them. I have created mock instrument drivers by overriding the functioning methods with empty methods in a derived child class, but I consider this application test code rather reuse code. The questions are a little ambiguous. I'm not sure if you're referring to a built application or application source code. Currently all my reuse modules are intended to be reused during dev-time, not run-time, so I'll address it from that perspective. I change major version numbers (and hence the module filename) only when backwards compatibility is broken, so any compatible updates are automatically included in the application source code the next time I open that project. Since new versions are incompatible by definition, I don't want applications to automatically use the new version. The application still loads the previous version of the library so it is not broken. Not so much in the same application, though there's no reason I know of that it would inherently break code. It's more so I don't have to fiddle around with making sure I have the right version installed for a given project. I can simply have them all on my dev computer at the same time.
-
That happens when the scope of the palette vis does not allow the active vi window to use them. If you open a vi that does have scope to use them, the x's will go away.
-
Short answer: Descriptive library filename appended with major version number. EventManagerLibrary__v1.lvlib MessageLibrary__v2.lvlib Long answer: [Pet Peeve alert!] The way LV ties namespaces to libraries has irritated me for some time and is (imo) clearly inferior to other modern languages. For example, the .Net framework separates the physical code organization (assemblies) from the logical code organization (namespaces). Labview can't do that. It's namespaces are simply a byproduct of the library file name and you can't create logical groups of related functions across multiple libraries. I gave up trying to create some sort of unified hierarchical namespace. Without the ability to separate the physical and logical organization any scheme I come up with is too fragile. (An ealier attempt to create a namespace tree by nesting libraries resulted in what my 12-yo daughter would call an "epic fail.") However, I have finally taken AQ's advice and starting using lvlibs to organize my code into modules, and despite the inconvenience of writing more wrapper methods I think it is worth it. It definitely helps me maintain a layered application structure and limit interdependencies. I include the library right in source code rather than adding the code to a library during the build. Doing it in source helps me maintain the separation (both in code and in my head) between the library functionality and the library api. If I was distributing a single class, I wouldn't bother putting it in a library unless I expected to add more classes to it in the near future.
-
Access the same object from parallel loops
Daklu replied to mike5's topic in Object-Oriented Programming
I agree with everything previously said in this thread, so let me add something a little different. You are asking the wrong question. Instead of "how do I access the same object in parallel loops," you need to ask "how do I want this class to behave?" Broadly speaking, there are three possibilities: By-val. Each new instance creates a new object. Branches create a copy of the object. (This is the "normal" way.) By-ref. Each new instance creates a new object. Branches refer to the same object. Singleton. All instances and branches refer to the same object. (You can create classes in which some data is by-val, some is by-ref, and some is singleton, but that's beyond the scope of this post.) By first defining the expected behavior for the class as a whole, you can build that functionality into the class itself in a way that doesn't break your application in other areas. If the class' built-in behavior doesn't fit your requirements at a certain point in the code, you add other code at the application level to fit the behavior you need there. Suppose your program will have lots of instances of a class, so you decide it should be by-val to simplify the programming. But in this one place you need by-ref behavior so you can access the object from parallel loops. That's where you would use the DVR or other techniques to enable that functionality. On the other hand, if it makes sense for the class itself to be by-ref, you can build that into the class members in a way that class users don't have to worry about DVR's, IPE's, queues, FG's, etc. The class user just needs to know that it's a by-ref object, and branches don't create copies. [Edit - Changing an object's behavior can only be done in a single direction. (By-val -> By-ref -> Singleton) You can make a by-val object behave like a singleton, but you can't make a singleton behave like a by-val object.] -
I second what Chris said. A screwdriver is a very useful tool if you need to tighten a screw. It's next to worthless if you need to loosen a hex bolt.
-
Nope, and nope. In general I don't think you need to recompile prior to a build as I would assume the build process includes a recompile. I could be wrong though... it's just what I've always assumed. Our tools are for internal customers to support product development, so our entire QA process is somewhat on the light side. ("Unit testing? Why bother?") We don't typically produce large applications that need nightly builds.
-
Cannot move or delete folder while LabVIEW is open
Daklu replied to Shaun Hayward's topic in Database and File IO
Here is my solution to this frequent annoyance. While it may be the windows api lock that is preventing the folder from being deleted, I think the root of the problem is how the LV code uses the api. Think about what would happen if windows did allow a working directory to be deleted out from under an application. Every time the application reads or writes from the working directory the application would have to first check to make sure the directory exists. I don't think that's a very good solution. It's not terribly difficult to store the current working directory in a variable and set the working directory to something like the root Labview folder. When the user initiates an action that uses the working directory such as the Open File dialog box, retrieve the previous working directory from the variable and use the windows api to set the working directory before calling the open dialog. Or better yet, don't use the OS working directory at all as part of the UI. -
That's what I do. Check out the entire project, recompile, check it all back in. We have lots of checkins that are nothing more than recompiles.
-
Inserting consistent error handling into a project after the coding is mostly complete can be tricky. In those cases I'll create a 'RaiseError' sub vi that takes an error code as an input. Internally the RaiseError sub vi looks up the correct error description for that error code and constructs an error cluster, which it sends out on the error wire. I like to use "Create Error Cluster from Code.vi" from vi.lib, but you can build it however you want. If I'm creating the application from scratch I try to build a more unified approach centered around my Message library. "Expected" errors are immediately trapped (meaning the error wire is cleaned), packaged into an ErrorMessage object or ErrorMessage subclass object, and put on the message queue to be be handled by the message handler. "Unexpected" errors propogate on the error wire to the start of the next loop. When my DequeueMessage.vi detects an error on the input, it traps the error, packages it in an ErrorInMessage object, and sends that out to the message handler. The queue remains unchanged. If the Dequeue primitive generates an error message, the error is trapped, packaged into a QueueErrorMessage object, and sent to the message handler. The ErrorInMessage and QueueErrorMessage classes are subclassed from my ErrorMessage class, which is in turn subclassed from my Message class. All of these classes (as well as my MessageQueue class) are part of my Message library. I typically derive new classes for each application specific error, but they can be packaged into the generic ErrorMessage object also. I don't think my approach is unique but I do feel like I have better control over error handling when I do it. My only other comment is that you'll get more reuse mileage out of your error logging code if you make sure it is independent from your error handling code. Error handling code is typically application-specific; error logging code can easily be reused across projects. I favor using the error logger inside the error handling code--others may have different ideas.
-
Same name, both places. Though like many others I don't post to or read NI forums too much. Too much traffic.
-
The link is for the original "basic" OOP presentation. He's referring to the "advanced" presentation that was mentioned during the webcast. The VUG presentation list can be found here. It doesn't look like the advance OOP webcast has been done yet.
-
Launching a Dynamic VI Staticly
Daklu replied to Ryan Podsim's topic in Application Design & Architecture
Err... when did this behavior change? 8.6 loads all library VIs and I thought 2009 does as well. Unless I'm not fully understanding what you mean by "load." -
I can't say whether you're going down the right road... it all depends on where you expect to be at the end. There's nothing blatently wrong with what you've done that I can see, though I did not execute the program and I have little experience with system tray notifications or .Net callbacks. The biggest "error" is the methods "Show FP Callback" and "Sys Tray Icon" maybe should be included as part of the class--it depends on how you want users to interact with your reuse code. Since you're making a class for other developers to use, you need to think about how you're going to present your class' functionality to them. In other words, what do you want the api to look like? The best api's are simple and intuitive. Naming your methods correctly goes a long ways to accomplishing that goal. Class methods are generally named with a verb-subject pair, such as 'Create Icon' or 'Show FP Callback.' This makes it clear to your class user what the vi does. Names like 'Callback,' 'Tray Icon,' and 'Balloon' don't identify what the method does. Consider renaming them to something more descriptive. Use the class' scoping abilities. Every public VI in your class becomes part of the class' api and it can be very difficult to change those in future versions. The 'Sys Tray Icon' vi wraps 5 other vi's that create the necessary resources and shows the icon in the system tray. Do users need to have each of those 5 sub vi's available to be called independently, or should you make them private and wrap them all in an Init method? Each method has it's advantages.
-
Don't use the built-in dialog boxes in the General Error Handler. Feed the Code, Source, and Error outputs from the General Error Handler into your own dialog box that exposes methods to close it. We have a timed dialog box that displays the error for a certain amount of time before automatically closing. This gives an operator time to respond to the error without blocking the testing if no operator is present.
-
Looks like another new Apple device is in the works... (Courtesy The Onion)
-
Well I've been trying out Enterprise Architect on the basis of Paul's experience, and it turns out it is very similar to StarUML. Maybe Sparx used Star UML source code? Maybe they hired the StarUML developers? I dunno... but moving from one to the other is no problem at all.
-
Nope. The compiler and linker are part of the dev environment, not the run-time engine. If you don't have LV installed on the target computer you're out of luck. The most obvious causes for needing to recompile the calling VIs would be, a) unintentionally modifying something in the main part of the application, or b) not properly decoupling the plugins from the main app, or c) changing the interface to the plugins. You already copped to c, but I'll bet you have some b in there too. a) Did you change anything in the plugins that propogates up to the main app? Typedefs are a prime suspect here. Changing a typedef requires a recompile for every VI that uses it. I generally avoid exposing typedefs across code modules for exactly this reason. b) You mentioned adding terminals to the connector pane, so you are probably calling your plugins by simply dropping them on the VIs in your main app. I've never tried replacing a vi that is statically linked to an executable, but it wouldn't surprise me at all if it doesn't work. To properly decouple your plugins you need to call them dynamically at runtime by feeding the path into the Open VI Reference and Call By Reference Node primitive nodes. c) Again pointing to the altered connector pane, if you're using the Call By Reference Node primitive to make dynamic calls, you can't add conpane terminals without changing the conpane prototype wired into the Open VI Ref prim in the calling code. In other words, you've changed the interface to your plugin. (There are ways you can add terminals to a plugin, but your original source code has to be written to accomodate it.) If you think you might need to change the data sent to or received from a code module, wrap it in a class. That does make me wonder... why did you add terminals to the plugin if you're not using any of those terminals in your main app? (I'm making a bit of a leap here based on your comment about only needing to open and resave the project to fix it.) ---------------- VI Package Manager is a very good tool. At first glance your problem appears to stem from the application's architecture, so I doubt that it would help you at all in this situation.
-
Labview OOP hasn't progressed to the point where classes can have display widgets automatically associated with them. We know this is an area of interest for Labview R&D but don't know when (or if) it will be implemented. I've found that I have to recreate almost all of the common object-based infrastructure that is readily available in other languages. There really aren't any higher level api's (like Swing) for LVOOP. Not being well-versed on subpanels, I'd probably look into building an observer GUI component from scratch that would update on the object's data changed events. However, I'm sure there are more direct ways to accomplish want you want.
-
This idea has been promoted to In Development. Being the author of the least kudo'd idea in development seems a dubious honor, but what the heck. I'll take what I can get. (Given the realities of the business world, I suspect Darren worked on this more or less on his own time and the status was changed after he finished it.)
-
Modified the existing vi. Oh well, I guess I'll chalk it up as Universal Conspiracy against me. *shrug*
-
Glad to hear you're making changes Bob. My biggest problem with exercise is that it is so booorrriiiiinnnggg. If there were a reasonable way for me to work on my LV ideas while going for a walk I'd be more inclined to do it.