Mark Smith
Members-
Posts
330 -
Joined
-
Last visited
-
Days Won
5
Content Type
Profiles
Forums
Downloads
Gallery
Everything posted by Mark Smith
-
QUOTE (Ic3Knight @ Jun 2 2009, 01:41 PM) Just to see what Subversion's all about, you can set up a simple repository using the "file:\\" access mode rather than a server. While this is not considered best practice except for personal repositories, it's incredibly easy. Just install the TortoisSVN package and open the help file, search on create. It will tell you how to create a repository and then access it using simple file access rather than access thru a server. Later, if you like what you see, you can install a server and access the repository you already created. BTW, I use this with two and three person teams (we seldom if ever work on the same code at the same time) and it has not caused problems yet, although we are in the process of finally getting IT to set up a real SVN server and doing it the right way. Mark
-
Application:All VIs In Memory Property returns Class ctls?
Mark Smith replied to Mark Smith's topic in LabVIEW General
QUOTE (Aristos Queue @ May 5 2009, 09:40 AM) Thanks for the info Mark -
Application:All VIs In Memory Property returns Class ctls?
Mark Smith replied to Mark Smith's topic in LabVIEW General
QUOTE (normandinf @ May 5 2009, 08:26 AM) Now that's interesting - I'm running 8.6 and I get this window when I select help for "Application:All VIs In Memory Property" from the context window - are we talking about the same help menu? http://lavag.org/old_files/monthly_05_2009/post-1322-1241534189.jpg' target="_blank"> Thanks, Mark -
I was a little surprised to open a Application:All VIs In Memory Property node and discover that it returns Class .ctl types and any typedefs associated with the class. Is this intended behavior? The help for Application:All VIs In Memory Property says Available with control VIs: No Can anyone edumacate me? thanks, Mark
-
QUOTE (esqueci @ May 4 2009, 09:15 AM) You are correct as far as I know - you'll need to dynamically call the wrapper VI that calls your DLL in order to launch a new thread for that VI to keep your DLL call from blocking. With that said, it seems like you're building LabVIEW code into a DLL and then calling it from LabVIEW - seems like the hard way to do things. I would also think that you could call the DLL in a loop - if the DLL has enough info to know how many times to loop, it seems like you could make a call to a DLL method and get that info - like how many times to iterate thru a for loop. If the call in the DLL is in a while loop, just return whatever exit condition you use to terminate the while loop from the DLL call and use that to terminate your loop around the DLL call. Mark
-
Thoughts on large amount of config data
Mark Smith replied to dblk22vball's topic in Application Design & Architecture
QUOTE (dblk22vball @ May 5 2009, 06:11 AM) I manage large config files two different ways, but they both start the same way - build a cluster (always typedef this cluster - it makes changes so much easier!) that contains all of your configuration fields and then use one of the tools available to serialize the cluster contents to text and then to file. Method 1 - use the Flatten to XML then Write to XML File to create an XML tagged text file and use Read from XML File and Unflatten from XML to recover the file contents. Attached is a simple example. Advantages - - easy to use - just put whatever you need for config info in the cluster and then flatten to xml and write to file - All native LabVIEW code Disadvantage - harder to read and edit manually than a .ini style file - you won't be able to read old configuration data if you change the cluster definition Method 2 - use David Moore's Write Anything and Read Anything files http://www.mooregoodideas.com/File/index.html Just wire your configuration cluster to the input of Write Anything and it will automatically create a .ini style text file - use Read Anything to read the file and repopulate the config cluster Advantages - - creates easy to read .ini style files - quick! The performance is more than adequate even on config files with hundreds of entries - if the cluster definition changes, the Read Anything will still read the old config file - it just provides its default data for any fields not found Disadvantages - Mostly open code - there's one password protected VI in the bunch - not native LabVIEW I use both but for most simple configuration tasks I use method 2. OpenG also has a set of config file VIs that operate much like David Moore's, but the last time I used them (which has been awhile) I found it easier to use Moore's VIs and the performance to be better on larger config files. Mark Download File:post-1322-1241527217.zip OK - I saw JGCode beat me to the punch but I'll post this any way! -
QUOTE (ACS @ Apr 30 2009, 10:00 AM) Here's a handy little VI - just wire a ref of whatever VI you want the version of - gives the exe version in the runtime and the rev history number in development Mark http://lavag.org/old_files/post-1322-1241109404.vi'>Download File:post-1322-1241109404.vi LV 8.6
-
QUOTE (n00bzor @ Apr 29 2009, 03:04 PM) If you're running out of ports (I'm assuming the "local port" control is unwired), then it most likely means none of your connections are getting closed properly or you're really running out of local ports. A TCP connection that reads from a port won't release its port immediately upon a close - it goes into FIN_WAIT and TIME_WAIT states to allow for packets wandering around the net and such to arrive. Opening a connection for write only allows it to release upon close (or as soon as all data is sent). http://www.developerweb.net/forum/showthread.php?t=2941 So, if you're looping thru connections at fast rate, then you might actually run out before the ports before they exit the WAIT states and become available again. With that said, I can't imagine how one would run out of local ports in any kind of system - you should have at least hundreds available. Assuming you're on a windows machine, run netstat from the command window and see what ports are in use when you get this error. Mark
-
QUOTE (gerb27 @ Apr 28 2009, 11:30 AM) I saw some interesting behavior on my sample shared variable project - if I right click on my client lvlib and select New->Variable, as soon as I start to modify the variable name I get the warning from the error message LabVIEW: Invalid variable name. The name of a variable cannot start with a single quote (') or contain a backslash, forward slash, or any of the following backslash '\' codes: \r \n \t \b \s. But, I can then add a space and something else (Like Variable 1) and the editor window is happy - but this as slash codes display is Variable\s1 so it now contains an illegal character (the \s) but the editor window doesn't complain any more. This doesn't really make sense - so I suspect that maybe the editor is allowing illegal values - make sure you don't have anything in your variable names but letters and maybe underscores and numerals - no spaces, carriage returns (I noticed an <Enter> from the keyboard will close the editor dialog when the focus is in the Name control - did it leave a CR?), tabs, linefeeds, or backspaces. Mark
-
ActiveX WinHTTP
Mark Smith replied to LVBeginner's topic in Remote Control, Monitoring and the Internet
QUOTE (rolfk @ Apr 23 2009, 11:18 AM) Yep, I misspoke - I should have said LabVIEW doesn't support proxy servers since the TCP/IP layer is a lower level protocol. But the OpenG solution looks like a good way to avoid activeX Mark -
ActiveX WinHTTP
Mark Smith replied to LVBeginner's topic in Remote Control, Monitoring and the Internet
QUOTE (LVBeginner @ Apr 23 2009, 09:21 AM) Although the repository page only lists 8.5 as the version, the zip archive includes versions for 7.1 and 8.0 for the XML-RPC code. So you can download it and take a look if you're interested. Mark QUOTE (Mark Yedinak @ Apr 23 2009, 09:55 AM) If you are only sending some basic pages to the server I think you would be better off building your strings and sending them via the native TCP connections. If you do a trace using your ActiveX version you should see what messages are being passed to the server. Your earlier version may have simply been missing a message that was generated by the ActiveX component. The TCP VIs are fairly basic. You would essentially need to use three of them. They would be the open, write and close VIs. More likely than not you will want to open the connection on port 80. What types of problems were you encountering? IIRC, the original problem here was accessing web pages from behind a proxy server - LabVIEW TCP/IP vi's don't have any automatic way to handle that and WinHTTP does. Still, one could write some LV code to handle building the requests to the proxy server, if one wanted to. Mark -
QUOTE (orko @ Apr 21 2009, 12:18 PM) Use class member VIs to call into the class, but don't include class controls or indicators on those VIs - then you can call the action engine. The only control(s) you need to expose from the caller is the unique ID so the action engine can look it up and a control you'll use to set the class data, if you want to set a class value. If you want to return a class value, just include whatever indicator you need. Now, use the ID to call into the get method of the action engine, perform whatever on the object, and then use the set method to return that object to the action engine collection. No class types were exposed to the outside world. It really doesn't matter if the object pulled from the collection is the same one that gets returned as long as the state of the new object is correct and it carries the same unique ID. In fact, I don't really know if the object I pulled from the array is the same one as the one I return - anybody care to educate me? - The operation is to wire the object retrieved to a class method, bundle something, then pass the wire back to the action engine and put that element back in the array - is this still the same object? Of course, this presumes that class member VIs that don't include class types as arguments can be used as interfaces to DLL's - I don't see why not, but I haven't tried. Mark
-
QUOTE (Umit Uzun @ Apr 21 2009, 02:44 AM) Use the LabVIEW "Flatten to String" function - this will serialize a LabVIEW data cluster into a byte stream that can then be unpacked by the C++ app into a C++ struct - for example LabVIEW cluster: Numeric (Double), Numeric (U32 Int), Array (U16) (note that this must be a populated array of the same size as the target struct) to pass this to a struct of struct LVData { double x; int y; short array[100]; }; Then just wire the cluster up to flatten to string (wire a false constant into the "prepend array or string size? " control) and then pass the flattened string to your C++ app. Now that app will have to deserialize into a struct. Mark
-
QUOTE (orko @ Apr 20 2009, 01:21 PM) OK - let's get back on topic I have similar but not quite the same design problem I'm addressing. I'm using LVOOP and LuaVIEW in a new tester framework that I'm implementing. My issue is that I'm using the object/method paradigm in Lua to instantiate script objects and then call methods on those objects. To do that, I'm using the functionality that the Lua authors at CIT designed in where the class name gets loaded into a Lua table (here, the class name means a naming convention of the Lua callable VI) and then subsequent calls to that object use that class name to get the path to the correct function. Here's how it might look in Lua -- create the object myInst=Instrument.new("myInst") -- call a method on that object myInst:configure("some config string") This would call into two VIs named Instrument.new_lua.vi and Instrument.configure_lua.vi. myInst is a Lua object and can contain a 32 bit refnum. To create a persistent "call by reference style" object, the VI called by the new method is an action engine (smart LV2 global) and it uses the argument "myInst" to new to create an instance of the class and store it in a array. This "instance engine" also has the ability to get (return) an existing object, set an existing object (get the object, expose it for some data modification, and then place it back into the array), and delete an object - it does this by name lookup. This is more than acceptably fast when the number of objects of any given class is expected to number in the tens. The Instrument.new() method returns a LV string refnum that contains a string that looks like <LVClass name>_<methodName>, or in this example, Instrument.lvclass_myInst. The LuaVIEW calling convention passes the object back in the myInst:configure() call so I can get the class type and instance name. Now I can retrieve that object from the action engine and operate on it. This is all working well. This also sounds similar to AQ's suggestions. My concern here is how to keep all of the LV components of the scheme alive between calls to the DLL. In my situation, LuaVIEW works because all of the Lua callable VIs I use get "registered" at run time and that means the action engine gets loaded and stays loaded during the lifetime of the script so I can be sure that any objects the action engine creates don't get lost because the action engine went out of scope. With a LV DLL, it would seem that the first call to the DLL to create a "new" object would have to start a background thread that stays running even after the call returns - otherwise, the context of that DLL call will disappear as soon as the call returns. Is my understanding correct? Here, I can see a call to the DLL that creates a new object of a given type and returns some ID to that object. Now, subsequent calls on that object pass in the ID and the LV DLL gets the ID and gets the object from the action engine and does whatever. How you get all the object data set may be more problematic since you can't just create a LV object and pass it from the C/C++ code (or whatever) - you'll have to expose accessors and then call those with the correct object ID - or something like that. Mark
-
Fundamental Exam Confusing Questions - please post
Mark Smith replied to Minh Pham's topic in Certification and Training
QUOTE (Chr1sG @ Apr 20 2009, 05:45 PM) I don't think there's anything tricky or misleading about 30 - The answer to 30 is Highlight Execution, since the problem clearly states the program is already running. I would agree that 16 could be a little confusing, since I don't think it's 100% clear what "ordered" means in this context. I think that B means "you cannot always count on an array element introduced as element n to be in the n position when you go the retrieve it from the array", in which case this is the false statement. There's some small chance that they're talking about sorted, in whch case this would be true and E would be the correct answer. Also, the answers are mutually exclusive as that is typically the rule in this type of multiple choice exam so saying that you couldn't choose E because all of the above are correct is a little disingenuous. Mark T Mark -
LV and LV-executable on 2 machines
Mark Smith replied to torekp's topic in Application Design & Architecture
I looked at using shared variables for communication between two machines (one w/LabVIEW and one with just the RTE - and the shared variable engine) and found it to be a little confusing to set up but ultimately it worked as advertised. The machine w/LabVIEW acts as the client and the exe/RTE machine is the server. I have attached a sample project that I swear I loaded from the NI site but now I can't find it (that's why I'm attaching the project and not the link!) that demonstrates a simple client/server using shared variables. This project is in 8.5. MarkDownload File:post-1322-1239988028.zip -
Changing control typedef at runtime
Mark Smith replied to jabson's topic in Application Design & Architecture
QUOTE (neBulus @ Apr 17 2009, 09:55 AM) First, I'm pretty sure you can't change a type def at run time in an executable- it's a compiled component of the code. That said, if you're running in the dev environment, maybe you can script that? I don't know, I'm not a LV scripter. I think LVOOP is an interesting idea, but let me make sure I understand how this is going to work. You create a parent class that supports the header and a generic message body (byte array?). When a message comes in, you then read the header with the parent and then cast the object to the required type by passing the parent wire into the child that's specialized for that data type. Then the child unpacks the body into the correct structure (control). Then that child has to display the control somehow - thru opening itself in a subpanel, perhaps? The child classes could be called dynamically from a library of VI's or built into the exe. If you have the children built into the exe, you'll have to recompile and re-distribute whenever a new definition is required. If you deploy the child classes as libraries (folders of VIs on the target machine), then you could use a scheme where the header definition maps to an entry in some list of children (maybe in an ini file), read the list from your main app, then use the entry in that list to load the child dynamically. Now, you have an app that you can extend forever (as long as the header defintion doesn't change) without ever replacing the exe - just add children to the library to support the new data structures. Mark -
Here's the easy (if not at all obvious) way to get the local machine name (including domain) and/or IP address, if that's what you need http://digital.ni.com/public.nsf/allkb/B66...62572F40078FC96 Mark
-
Are there limits to the number of cases, etc?
Mark Smith replied to twinsemi's topic in Application Design & Architecture
QUOTE (twinsemi @ Apr 16 2009, 09:32 AM) I have found one of the only ways to get rid of insane object errors is basically throw away the problem VI and start over - this isn't quite as bad as it sounds - just open a new VI and start copying parts from the old block diagram one section at a time. Save after every copy operation. After a while, you may copy something that gives the insane object error. At that point, throw away that section of code and start rewiring everything in it from the function palette. Then try saving again. If that works, start copying again. Rinse and repeat until the entire VI compiles and saves correctly. Time consuming but it works since there's something in the original source that just won't run correctly and LabVIEW just can't identify it and flag it at compile time so you can't find it and take it out without a trial and error process like this. Mark -
QUOTE (Mark Yedinak @ Apr 14 2009, 09:32 PM) The packing scheme isn't important to the serialized data because I have to send a U16 as 16 bits and the receiving application has to accept that as 16 bits - whether the receiving app then wants to pack 16 bit data on 32 bit boundaries or 16 bit boundaries internally is up to the receiving code. It's a much easier problem than handing the receiving app a pointer to a byte array in memory and then hoping all gets unpacked correctly! Mark
-
QUOTE (Dirk J. @ Apr 14 2009, 03:25 PM) The problem I remember was due to header changes (LV7.1->8.0, I think) causing the read to fail. I don't know if the data encoding changed or not because at that point I just used the older version of LabVIEW to open the data and save in a data-neutral format (strings, I think) that I could read in the newer version. Mark QUOTE (Mark Yedinak @ Apr 14 2009, 01:54 PM) If you want to ensure compatibility couldn't you create a single binary buffer containing all of your data? If all of your data points are 32 bits then cycling through your array of 1000 data points and creating a single buffer with all of the data (4 bytes for each data point) would be a very fast process and when you read the data out simply dump every 4 bytes into an array element. Again, this process will be fast and you won't have to worry about NI changing the flatten to string format. This is what flatten to string already does - if you have an array of 32 bit values, it just streams that as one 32 bit value followed by the next and will prepend a 32 bit int (or not, if you tell it not to) to the data stream. Flatten to string doesn't carry any type data with the exception of prepended 32 bit size fields for arrays and strings - it's the bare binary image of your data. The only change I'm aware of in the way that LabVIEW flattens data was from 4.x to 5.x where the size of a boolean changed. All of the type info required in unflatten from string is in the data type that must be wired to the type input. As long as 32 bit ints are 32 bits and doubles follow IEEE specs, I don't expect there will ever be any problems. The fact that flatten to string used to expose a type descriptor string (7.x) is sort of beside the point. I use flatten to string (and unflatten from string) extensively to communicate with C++ apps through TCP/IP. All I have to know is the data struct the C++ apps expect and I can flatten and send the data with no problems. U32's are U32's, doubles are doubles (as long as the endianess is known), fixed size arrays are LabVIEW clusters (use the array to cluster), etc. Mark
-
I certainly hope the flatten to string protocol won't be changing anytime soon as that's how I serialize data for transmission over TCP/IP to and from non-labview targets. And I don't think it will. I think the subject of binary data files (and datalog files - that one has bit me on LabVIEW release changes) is different - at least I hope so. Mark
-
QUOTE (crossrulz @ Apr 14 2009, 01:56 PM) Oh, you young child (just kidding) - you probably have never worked with 640X400 (or maybe even 800 X 600 if you were lucky) displays - that was typical when I started on LabVIEW 4. Sometimes those screens look crowded because we just didn't have any more space to work with. Mark