-
Posts
1,068 -
Joined
-
Last visited
-
Days Won
48
Content Type
Profiles
Forums
Downloads
Gallery
Everything posted by mje
-
I don't believe so. By my reading, a pseudo-random GUID conforming VI would follow the logic in section 4.4. Given the following syntax: typedef struct { unsigned32 time_low; unsigned16 time_mid; unsigned16 time_hi_and_version; unsigned8 clock_seq_hi_and_reserved; unsigned8 clock_seq_low; byte node[6];} uuid_t; So something like this (all optimization aside): Also of note:
-
This recommendation might be of interest. Specifically if a generation VI is created, all bits are not random (section 4.1).
-
I'd say no, I still see the red marks on my system with some of the menus from the library I posted. I can't say I understand why some have x marks and some don't. My Application palette does not have the glyphs, but the MessagePump one does. Both are in the same library, and the VIs have the same scope. There is no license associated with the library. I will post this to the ni.com soon, just giving it a bit to see if it resolves over here first.
-
I'd argue the function is too restrictive. About the only thing that can be said about GUIDs is they are 128 bit hex strings. Formatting of a GUID is not always enforced. Personally, I would use a regex more along the lines of ^\{?\w{8}-?\w{4}-?\w{4}-?\w{4}-?\w{12}\}?$ Even then, some common forms of GUIDs would still return false: (CA761232-ED42-11CE-BACD-00AA0057B223) {0xCA761232, 0xED42, 0x11CE, {0xBA, 0xCD, 0x00, 0xAA, 0x00, 0x57, 0xB2, 0x23}} I've never seen the one top one in use, but I've used the bottom one plenty of times before as it also turns out to be a valid C statement. The difficult thing is there is no standard to interpret. I'd recommend adding a VI to create a GUID, and then have Is a GUID.vi follow whatever format is used in the create function, while also being able to interpret whatever format(s) LabVIEW might present.
-
I've updated the library referred to by Mr Mike, it can be found here. When I use the palette included with the library, I get the red 'X' marks as shown in my previous post in this thread.
-
As this is being referred to in another thread, I'm updating the library to a more recent version 2.1. The library now requires LV2011. LabVIEW.Messaging.2.1-r1423-LV2011.zip
-
Hehe, I forgot I posted that preview. You're right, no palettes included. My current library is version 2.1 (despite that the palette says "2.0", oops file that one under "bug"). This version was compiled with 2011 as it uses the new start async call nodes. I'll get an export generated tonight and post it to see if the problem can be reproduced. I really ought to finish that library one of these days... Does it matter how the palettes were added to LabVIEW? All I ever do is edit the set manually via the advanced menu option and add the existing mnu file. Too busy (lazy) to create an installer for the library.
-
/shrug The X marks are annoying, but as long as the palettes work I don't mind much. Odd. Definitely not fixed though. LV2011, these are public methods of a public class in an lvlib:
-
It was fixed? I still get them on several of my palettes.
-
Interesting. You're right, add in some transport layer and you have a messaging system. In fact looking at your code I realize I've done exactly this for state machines in the past (the person being the model, and each method is a state). You just turned the problem up on it's head for me, I never thought to apply something like that to this problem. Cool indeed, -m
-
Ah, my bad, I was getting history confused. I meant 2009.
-
I can't say I'm a fan of that method. Each level of the hierarchy then maintains its own DVR. Worse is you can't enforce that you're always dealing with a reference type. Once the class is extended, there's no contract keeping descendants from storing by-value data in their class data. Someone who's handed a wire several levels down the hierarchy has no way of knowing if they can branch the wire or not.
-
I'm wondering what some of you have settled on as best practice for defining a class' interface when the main use of a class will be through a DVR to that class. Specifically I'm referring to the dynamic interface, that is the collection of member VIs which are dynamically dispatched. For those who haven't really explored class DVRs, the caveat is that all DVR refnums are strictly typed*. If I have a VI with an in-out set of terminals of type DVR<Type=Parent.lvclass>, it is a static interface. When I then create Child.lvclass, I can't override this VI with a new one having terminals DVR<Type=Child.lvclass>. If the user is only ever handed a DVR to one of these classes, we really only have two options as I see it. Option 1: Design the class entirely by value This leaves the onus on the user to have to wrap every call (or chain of calls) up in an IPE: The good news is this allows exact control over when you're locking down access to the refnum. For this reason alone I think this is the way to go, as the inherent synchronization this allows is a fundamental guard for data integrity if that DVR is floating around several different parallel tasks. The bad news is this way of doing things is ugly as sin, it can quickly become a mess of Case+IPE structures scattered throughout the diagram. Option 2: Create wrappers for the public API The idea is here we have a static VI which wraps access to each public dynamic VI: Usage of such a class looks something like this: OK, using the DVR is now much cleaner, but there's a few caveats: Lack of synchronization is in my opinion the biggest. There's an inherent lock/release involved with each call to a wrapper method. There's absolutely no guarantee that some other process won't operate on the DVR between the call to WrapperA and WrapperB. I'd have to add extra layer of synchronization to allow this, and to be honest, I already had one by virtue of the DVR. This is the fundamental reason I've abandoned this type of pattern. Though as long as I keep the by-value interface public, nothing would stop me from using a Case+IPE when I need to enforce an atom of operation... Another problem is extending the API with a child class becomes ambiguous. Maybe I want to add a new public dynamic method. What do I do? I can create a wrapper method, and have it operate on a DVR<Type=Parent.lvclass>, but this is an absolute nightmare as far as synchronization and type safety goes: You could also create the method typed to a Child DVR, but that really only changes where the cast is placed, and besides, if you're trying to insert the wrapper VI in a call chain with an API defined across multiple levels of inheritance, it becomes really messy and cumbersome. Learned this one through experience. Has anyone come up with a better "pattern" (for lack of a better word) when dealing with DVR based class interfaces? Experience has taught me that Option 2 is just plain broken. Option 1, although ugly and often cumbersome, is perfectly functional. Attached is a sample project (LV2010SP1). Regards, -michael DVR Interface Example.zip *I realize there's a whole other discussion about what could happen if DVRs weren't statically typed, or if we had another type of terminal which adapted to type, or if pigs could fly. But the reality here is right now we have static DVR refnums, so let's please restrict ourselves to how we work with them, not what could be.
-
I'd say yes, provided you're in LV2010 or later of course.
-
I find I use the error code lookup VI quite regularly. Can't remember the name, but the one that takes an Int32 as an input and transmogrifies it to a string with the error description. Has a hideous blue and pink icon, called something like Error Code DB lookup? If you bury down into the error handler VIs you'll find it. Other than that, practically every project I've created in the last three years uses the variant library already mentioned, or rather my own library which extends it.
-
Class Default Value from Fully Qualified Name
mje replied to mje's topic in Object-Oriented Programming
Yes, there's no use case that wouldn't already be covered by the path based VI, and using a QN would even be more limiting since it would require the class to already be loaded. I was just doing some brainstorming about serializing a plugging based object for transfer across application boundaries. Part of the serialized data will have to be a list of types that are contained in a piece of data. The problem is though we can't use paths- who is to say the paths will be the same from one system to another? Relative paths aren't acceptable either, the objects might not even have a common base path. Let's work on the assumption there's already a mechanism in place to ensure whatever I need will already be in memory. During load I would take some kind of UID and do some cross referencing to determine the path I need to load. The thing is though, LabVIEW has already done all of this work for me. If I use the class' QN as my UID, LabVIEW should be able to resolve it for me. Like I said, with a little extra book keeping, this can already be done if I build some way of cross referencing my QN to a path, but that work has already been done for me by the RTE/IDE. I just hate re-inventing things. -
Specifically any of the Android tablets. I know Invision has created an iOS application and is apparently great, but they've neglected the Android platform to date, so all we have is whatever interface is presented via the standard browser. The old mobile skin was pretty dumbed down as far as features go, and try as I did, couldn't find a way to force the full version of the site. Maybe the new mobile skin works great, and is perfectly functional, I haven't had the chance to test it out since the switch was pulled to force it, so please don't think I'm being critical. Yet.
-
So the Get LV Class Default Value.vi does a great job, insomuch as it will load from memory when it can, but that still means I need to know the path of the class I want to load. Is there any reason we don't have the capacity to load a class via fully qualified name? This of course would only work for classes already in memory. Seems like it might be useful for factory patterns, among other things. Maybe my classes are scattered across several disk locations and I don't want to worry about keeping track of what comes from where. All I know is I want a MyLib.lvlib:MyClass.lvclass, regardless of where it came from or who brought it into memory. -m
-
Boo. I guess I should have been more specific. The old forum had such a busted mobile version where so little could be done, and never allowed you to force a full version. When I saw the mobile version delivered to my phone was so nice and functional, I was happy. Only later did I realize it was the full version of the site. The new mobile version seems functional, though it will be annoying we can't switch back to full version on larger "mobile" devices (tablets).
-
This. I absolutely agree. Also any dialog boxes that must be shown should never be yes/no/ok/cancel/etc. Make a proper UI with large buttons that clearly explain what action will happen if you click on the button. Windows 7 did a lot of this, and though they went a little overboard in my opinion it was definitely a step in the right direction.
-
Nice, the mobile version of the site looks good and is way more functional than before.
-
The whole under sea vent and life meme has me thinking of Steve Zissou. I won't be able to contribute anything constructive since that theme song will be stuck in my head for days...
-
Sigh... Thank you. I...I don't know how I managed to get so many of my input/outputs overlapping like that. Maybe it was because I was right clicking on wires to insert nodes rather than placing them myself? I...urgh. Some days it does not pay to wake up.
-
I've got some weird feedback node behavior, and I'm hoping it's just that I don't understand these blasted things. What does it mean to initialize a feedback node? Seems simple enough to me, wire up a constant, and it's initialized such that the first value returned is what you've initialized it to. Well, not quite: Plop this snippet in a blank VI, and run it. What do you get? I've confirmed these results in LV2010 SP1 and LV2011: Compile/Load value: 2 Compile/Load Incremented: 1 First Run value: 2 First Run Incremented: 1 Each subsequent call to the VI as long as it remains in memory increments both the Compile/Load values by 1. I expect this due to scoping the initialization as Compile/Load. However, there are other things amok: Why is the initial value returned from either feedback node 2 when it has been initialized with 1? Why is the incremented value one less than the original value? Help?