<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-19928387</id><updated>2011-12-13T19:55:59.115-08:00</updated><category term='Coding'/><category term='Mac OS X'/><category term='Steve Jobs'/><category term='Macintosh'/><category term='LabVIEW'/><category term='Market Share'/><category term='Documentation'/><category term='Computers'/><category term='Good Code'/><category term='File Systems'/><category term='ZFS'/><category term='Mac'/><title type='text'>The MacView</title><subtitle type='html'>Virtual Instrumentation from a Mac perspective</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://themacview.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19928387/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://themacview.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Marc Page</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-KXZHHLyZcGU/AAAAAAAAAAI/AAAAAAAAJuU/PGlqPNBP9l4/s512-c/photo.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>31</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-19928387.post-6458152794349464266</id><published>2010-06-03T01:00:00.000-07:00</published><updated>2010-06-03T01:00:00.677-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Macintosh'/><category scheme='http://www.blogger.com/atom/ns#' term='Mac'/><category scheme='http://www.blogger.com/atom/ns#' term='LabVIEW'/><category scheme='http://www.blogger.com/atom/ns#' term='Coding'/><category scheme='http://www.blogger.com/atom/ns#' term='Mac OS X'/><title type='text'>How to Get All Mac System Colors in LabVIEW</title><content type='html'>Christina Roger's blog posts over at &lt;a href="http://blog.eyesonvis.com/"&gt;Eyes on VIs&lt;/a&gt; (specifically &lt;a href="http://blog.eyesonvis.com/2010/05/05/secret-labview-system-colors/"&gt;Secret LabVIEW System Colors&lt;/a&gt; and &lt;a href="http://blog.eyesonvis.com/2010/04/29/system-colors-dont-believe-your-eyes/"&gt;System Colors - Don't Believe Your Eyes&lt;/a&gt;) got me looking into the System Colors on the Mac. In doing so I wrote some VIs to query the OS directly (at least on the Mac) what &lt;b&gt;all&lt;/b&gt; the system colors are. You can download the VIs at:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://decibel.ni.com/content/docs/DOC-11077"&gt;Mac System Color VIs&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Both the Text Color API and the Brush Color API are very similar. They differ only in the function to call (duh) and the constants passed for what color to get. Here is GetThemeBrushAsColor.vi's block diagram:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_103x98gpMb0/S-MdexzGuUI/AAAAAAAAAHY/MhGSVQCwBzg/s1600/Picture+4.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 185px;" src="http://3.bp.blogspot.com/_103x98gpMb0/S-MdexzGuUI/AAAAAAAAAHY/MhGSVQCwBzg/s400/Picture+4.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5468246787158882626" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;My last post talked about &lt;a href="http://themacview.blogspot.com/2010/05/how-to-automate-creating-large-enums.html"&gt;converting a list of constants into an enum&lt;/a&gt;. I used this method (for both API calls) to create the enum input. For the RGBColor input, I just used an array of three Unsigned 16-bit Integers (Red, Green and Blue in that order in the array). The trickiest part was how to convert three u16s to a LabVIEW color code. LabVIEWs colors are an Unsigned 32-bit integer. The least significant byte is the Blue value. The next most significant byte is the Green value and the next most is the Red value, in other words: 0x00RRGGBB. The most significant byte is where LabVIEW stores magic flags, so we'll keep that zero. To convert from 16-bit values to 8-bit values, we just need the upper half of the 16-bit values. So we use Split Number primitive to get the upper half of the 16-bit values and use Join Numbers to put the colors in the right places.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_103x98gpMb0/S-MfQol9ZuI/AAAAAAAAAHg/ZnWACPdtOCQ/s1600/Picture+5.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 281px;" src="http://1.bp.blogspot.com/_103x98gpMb0/S-MfQol9ZuI/AAAAAAAAAHg/ZnWACPdtOCQ/s400/Picture+5.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5468248743192913634" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Then it's just a matter of getting the Call Library Function primitive set up correctly. There you go. Simple call to get all sorts of colors from the OS.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19928387-6458152794349464266?l=themacview.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://themacview.blogspot.com/feeds/6458152794349464266/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19928387&amp;postID=6458152794349464266' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19928387/posts/default/6458152794349464266'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19928387/posts/default/6458152794349464266'/><link rel='alternate' type='text/html' href='http://themacview.blogspot.com/2010/06/how-to-get-all-mac-system-colors-in.html' title='How to Get All Mac System Colors in LabVIEW'/><author><name>Marc Page</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-KXZHHLyZcGU/AAAAAAAAAAI/AAAAAAAAJuU/PGlqPNBP9l4/s512-c/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_103x98gpMb0/S-MdexzGuUI/AAAAAAAAAHY/MhGSVQCwBzg/s72-c/Picture+4.png' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-19928387.post-1494408540445835092</id><published>2010-05-06T11:45:00.000-07:00</published><updated>2010-05-06T12:05:08.561-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='LabVIEW'/><category scheme='http://www.blogger.com/atom/ns#' term='Good Code'/><category scheme='http://www.blogger.com/atom/ns#' term='Coding'/><title type='text'>How To Automate Creating Large Enums</title><content type='html'>I was creating some VIs to call the OS to get system colors directly when I ran into an annoyance. The OS defines a long list of constants (in this case kThemeBrush* in Appearance.h on the Mac). I wanted an enum in my VI API to make code calling my VI more readable (right click -&gt; create constant on the enum terminal creates an enum constant on the diagram). There were 62 enum values to enter. This was not something I wanted to type one by one into the enum control. So I came up with a way to automate much of the creation.&lt;br /&gt;&lt;br /&gt;First I searched for all lines in Appearance.h that contain kThemeBrush and a number. I took those lines and pasted them into a string constant and then wrote some code to parse out the constant name and value (see diagram below).&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_103x98gpMb0/S-MQkdvvCmI/AAAAAAAAAHI/ASRgvMwkfUw/s1600/Picture+2.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 132px;" src="http://2.bp.blogspot.com/_103x98gpMb0/S-MQkdvvCmI/AAAAAAAAAHI/ASRgvMwkfUw/s400/Picture+2.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5468232591204092514" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;So what does this diagram do? First I use vi.lib/AdvancedString/Normalize End Of Line.vi to make sure the line endings in the string are the LabVIEW platform line ending (\r on the Mac). I then use Spreadsheet String To Array primitive to parse the string into lines (one of my favorite text parsing tricks in LabVIEW). Then for each line I get the part before the equals (name of the constant) and then I get the part between the equals and the comma (constant value).&lt;br /&gt;&lt;br /&gt;I then copy the Ring to my VI, right click on it and select Replace and replace it with an enum. LabVIEW preserves all the strings. However, to get the appropriate value (enums by default use their (zero based) index as their value) I use the output array.&lt;br /&gt;&lt;br /&gt;The front panel of the VI has a Ring (not enum because you can't write the strings to an enum on a running VI). The constant names are written to the Ring values (Strings[]) and we output an array of the constant values. We right click on the array control and select Data Operations -&gt; Copy Data. Then right click on the array constant in the diagram below and select Data Operations -&gt; Paste Data.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_103x98gpMb0/S-MSFr7yxxI/AAAAAAAAAHQ/e0Go9maKVpI/s1600/Picture+3.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 201px; height: 107px;" src="http://2.bp.blogspot.com/_103x98gpMb0/S-MSFr7yxxI/AAAAAAAAAHQ/e0Go9maKVpI/s400/Picture+3.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5468234261460076306" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;This diagram converts the enum values to the constants from the header.&lt;br /&gt;&lt;br /&gt;I did this for two separate API calls (Theme Text and Theme Brush), each with their own set of constants. More reliable and much faster than doing it by hand.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19928387-1494408540445835092?l=themacview.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://themacview.blogspot.com/feeds/1494408540445835092/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19928387&amp;postID=1494408540445835092' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19928387/posts/default/1494408540445835092'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19928387/posts/default/1494408540445835092'/><link rel='alternate' type='text/html' href='http://themacview.blogspot.com/2010/05/how-to-automate-creating-large-enums.html' title='How To Automate Creating Large Enums'/><author><name>Marc Page</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-KXZHHLyZcGU/AAAAAAAAAAI/AAAAAAAAJuU/PGlqPNBP9l4/s512-c/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_103x98gpMb0/S-MQkdvvCmI/AAAAAAAAAHI/ASRgvMwkfUw/s72-c/Picture+2.png' height='72' width='72'/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-19928387.post-8427096059091423726</id><published>2010-04-01T12:30:00.000-07:00</published><updated>2010-04-01T13:10:59.948-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Computers'/><category scheme='http://www.blogger.com/atom/ns#' term='Macintosh'/><category scheme='http://www.blogger.com/atom/ns#' term='Mac'/><category scheme='http://www.blogger.com/atom/ns#' term='LabVIEW'/><category scheme='http://www.blogger.com/atom/ns#' term='Good Code'/><category scheme='http://www.blogger.com/atom/ns#' term='Mac OS X'/><title type='text'>Threading using Queues</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_103x98gpMb0/S7T02107yFI/AAAAAAAAAGc/gdcCMIsiZDg/s1600/QueueOperations.png"&gt;&lt;img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 348px; height: 362px;" src="http://1.bp.blogspot.com/_103x98gpMb0/S7T02107yFI/AAAAAAAAAGc/gdcCMIsiZDg/s400/QueueOperations.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5455254271651727442" /&gt;&lt;/a&gt;&lt;br /&gt;I found something unexpected today. I had written a VI to generate a report of the linkages between files in the LabVIEW distribution. It was a quick and dirty VI that basically did the following:&lt;br /&gt;&lt;br /&gt;1. Find all the VIs, Controls, Classes, Libraries, Projects, etc. in the LabVIEW distribution&lt;br /&gt;&lt;br /&gt;2. Read the linkage information from the file&lt;br /&gt;&lt;br /&gt;3. Write out a report on the file&lt;br /&gt;&lt;br /&gt;Here is a simplified version of what I was doing:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_103x98gpMb0/S7T4jatd-4I/AAAAAAAAAGs/y13Ax9hn_JM/s1600/SingleThreaded.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 187px;" src="http://1.bp.blogspot.com/_103x98gpMb0/S7T4jatd-4I/AAAAAAAAAGs/y13Ax9hn_JM/s400/SingleThreaded.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5455258336001653634" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;With this method, LabVIEW pegged the CPU at 100%. Well, LabVIEW pegged &lt;b&gt;one&lt;/b&gt; of my four CPUs at 100%. That's great because I can do other things, but I'd like this to finish as soon as possible. So I broke the three tasks into three separate loops that communicate through Queues. Below is the code:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_103x98gpMb0/S7T7rMkgERI/AAAAAAAAAG0/vUzlP2ueVq0/s1600/MultiThreaded.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 312px;" src="http://3.bp.blogspot.com/_103x98gpMb0/S7T7rMkgERI/AAAAAAAAAG0/vUzlP2ueVq0/s400/MultiThreaded.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5455261768179781906" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;My code went from using 100% CPU to 250% to 270% CPU. &lt;br /&gt;&lt;br /&gt;To use Queues to increase your threading, you need to be able to break up your code into tasks that can be run simultaneously. Usually if you are waiting for I/O, that is a good task. Here I have three disk operations (Directory Listing, Read From File, Write To File). It turns out the slowest of these is reading the linkage information from the file. So much so that the Queue of Paths stays full and the Queue of information to write remains close to empty. To help improve performance in a case like this, you can set a maximum Queue size (on the Path Queue in my case). I set the maximum size to 1,000 Paths. So the Read Link loop would always have no more than 1,000 Paths waiting for it. When it takes a Path from the Queue, the Directory Listing loop wakes up and puts another Path in the Queue.&lt;br /&gt;&lt;br /&gt;One trick is to figure out how to end the loops. With many of the LabVIEW APIs, you can loop until the Read operation returns an error, and in the Write loop, just close the reference. With Queues that doesn't work because you may close the Queue with data still in it (1,000 Paths, for instance). So instead we send some invalid data that we would not otherwise send (Not A Path in the Path Queue instance). When each loop finishes stuffing data into the Queue, it puts an invalid element in the Queue. Then the loops that read from the Queue know to stop when they see invalid data.&lt;br /&gt;&lt;br /&gt;I hope using this can improve the performance of your VIs. If you have any questions or improvements, please leave them in the comments.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19928387-8427096059091423726?l=themacview.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://themacview.blogspot.com/feeds/8427096059091423726/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19928387&amp;postID=8427096059091423726' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19928387/posts/default/8427096059091423726'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19928387/posts/default/8427096059091423726'/><link rel='alternate' type='text/html' href='http://themacview.blogspot.com/2010/04/threading-using-queues.html' title='Threading using Queues'/><author><name>Marc Page</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-KXZHHLyZcGU/AAAAAAAAAAI/AAAAAAAAJuU/PGlqPNBP9l4/s512-c/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_103x98gpMb0/S7T02107yFI/AAAAAAAAAGc/gdcCMIsiZDg/s72-c/QueueOperations.png' height='72' width='72'/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-19928387.post-6244307767124484164</id><published>2008-08-12T12:03:00.000-07:00</published><updated>2008-08-12T13:35:11.821-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Computers'/><category scheme='http://www.blogger.com/atom/ns#' term='LabVIEW'/><category scheme='http://www.blogger.com/atom/ns#' term='Good Code'/><category scheme='http://www.blogger.com/atom/ns#' term='Coding'/><title type='text'>Squeezing Parallelism Out of Your Diagrams with Merge Errors.vi</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_103x98gpMb0/SKHv7nQT05I/AAAAAAAAAC4/wVwg-6uxTj4/s1600-h/MergeErrorsInPalette.png"&gt;&lt;img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;" src="http://1.bp.blogspot.com/_103x98gpMb0/SKHv7nQT05I/AAAAAAAAAC4/wVwg-6uxTj4/s400/MergeErrorsInPalette.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5233728049409938322" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_103x98gpMb0/SKHerzGbETI/AAAAAAAAACw/tP_mt39srhI/s1600-h/MergeErrorsInAction.png"&gt;&lt;img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/_103x98gpMb0/SKHerzGbETI/AAAAAAAAACw/tP_mt39srhI/s400/MergeErrorsInAction.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5233709086014116146" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_103x98gpMb0/SKHw8ucFTYI/AAAAAAAAADI/be4L6LTLBGs/s1600-h/MergeErrorsUsage.png"&gt;&lt;img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;" src="http://3.bp.blogspot.com/_103x98gpMb0/SKHw8ucFTYI/AAAAAAAAADI/be4L6LTLBGs/s400/MergeErrorsUsage.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5233729168029863298" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_103x98gpMb0/SKHwIEybjVI/AAAAAAAAADA/RGcqUOdLMY0/s1600-h/MergeErrorsPriority.png"&gt;&lt;img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;" src="http://3.bp.blogspot.com/_103x98gpMb0/SKHwIEybjVI/AAAAAAAAADA/RGcqUOdLMY0/s400/MergeErrorsPriority.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5233728263496109394" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;There are two different ways to run your code on multiple cores in LabVIEW, static and dynamic. We've talked about the dynamic case before, getting a reentrant reference to a VI in a loop and running it. Now I'd like to talk about some simpler methods of squeezing parallelism out of your code.&lt;br /&gt;&lt;br /&gt;When I code, I find that I usually, for convenience, chain everything together with error clusters. So I would have one long string of actions, all tied together with an error cluster wire. It's convenient, but cuts down on LabVIEW's ability to run code in parallel. I have come to heavily use the Merge Errors.vi to help me run more code in parallel.&lt;br /&gt;&lt;br /&gt;Merge Errors.vi has three error clusters and an array of error clusters as input, and one error cluster as output. So you fork your incoming error wire to each of the sub-VIs that can run in parallel, and then take their output and run them into Merge Errors.vi. If you have more than 3 error clusters to merge, you can also drop a build array node for the remainder.&lt;br /&gt;&lt;br /&gt;When ordering is important, make sure the error you want to return to the user is in the first terminal. For instance the code shown below is a "destroy" VI. It must destroy the data, regardless of any errors coming in. This is like the close file primitive. You may have gotten an error while writing to the file, but you still want to close the file. However, we want to return any errors that were passed in to us, even if the destroy resulted in an error.&lt;br /&gt;&lt;br /&gt;The bottom line is, use the Merge Errors.vi liberally in your code to handle multiple errors instead of chaining all error clusters and preventing sub-VIs from running in parallel.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19928387-6244307767124484164?l=themacview.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://themacview.blogspot.com/feeds/6244307767124484164/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19928387&amp;postID=6244307767124484164' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19928387/posts/default/6244307767124484164'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19928387/posts/default/6244307767124484164'/><link rel='alternate' type='text/html' href='http://themacview.blogspot.com/2008/08/squeezing-parallelism-out-of-your.html' title='Squeezing Parallelism Out of Your Diagrams with Merge Errors.vi'/><author><name>Marc Page</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-KXZHHLyZcGU/AAAAAAAAAAI/AAAAAAAAJuU/PGlqPNBP9l4/s512-c/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_103x98gpMb0/SKHv7nQT05I/AAAAAAAAAC4/wVwg-6uxTj4/s72-c/MergeErrorsInPalette.png' height='72' width='72'/><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-19928387.post-8568169272105084824</id><published>2008-08-08T09:39:00.000-07:00</published><updated>2008-08-08T09:46:16.039-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Computers'/><category scheme='http://www.blogger.com/atom/ns#' term='Macintosh'/><category scheme='http://www.blogger.com/atom/ns#' term='Mac'/><category scheme='http://www.blogger.com/atom/ns#' term='LabVIEW'/><category scheme='http://www.blogger.com/atom/ns#' term='Good Code'/><category scheme='http://www.blogger.com/atom/ns#' term='Coding'/><category scheme='http://www.blogger.com/atom/ns#' term='Mac OS X'/><category scheme='http://www.blogger.com/atom/ns#' term='Documentation'/><title type='text'>Simple Preferences VIs</title><content type='html'>NIWeek was very informative. I got to talk to a lot of customers who use Macs and got a lot of feedback.&lt;br /&gt;&lt;br /&gt;I was talking to Travis Pape (pronounced poppy) about his really cool iBike app (LabVIEW built app for Windows and Mac that allows access to iBike computer). We were talking about the difficulties he was having with preference files, and I suggested he simplify the code.&lt;br /&gt;&lt;br /&gt;I wrote two VIs that access the OS preference mechanism. They allow you to store key/value pairs for your application. I've posted these VIs at:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://decibel.ni.com/content/docs/DOC-1832"&gt;http://decibel.ni.com/content/docs/DOC-1832&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Another example of using vi.lib/Platform/CFString.llb and CallLibraryFunction nodes. Took about 20 minutes to look up the functions, wire it all up, and then use &lt;a href="http://community.ni.com/examples/polish-vis "&gt;Polish VIs&lt;/a&gt; to add the documentation.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19928387-8568169272105084824?l=themacview.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://themacview.blogspot.com/feeds/8568169272105084824/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19928387&amp;postID=8568169272105084824' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19928387/posts/default/8568169272105084824'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19928387/posts/default/8568169272105084824'/><link rel='alternate' type='text/html' href='http://themacview.blogspot.com/2008/08/simple-preferences-vis.html' title='Simple Preferences VIs'/><author><name>Marc Page</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-KXZHHLyZcGU/AAAAAAAAAAI/AAAAAAAAJuU/PGlqPNBP9l4/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-19928387.post-5604611064472492427</id><published>2008-04-21T07:05:00.000-07:00</published><updated>2008-11-12T21:57:19.428-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Macintosh'/><category scheme='http://www.blogger.com/atom/ns#' term='Mac'/><category scheme='http://www.blogger.com/atom/ns#' term='LabVIEW'/><category scheme='http://www.blogger.com/atom/ns#' term='Mac OS X'/><title type='text'>Its The Little Things</title><content type='html'>First off, talking of little things, my girls are now a year old. For those of you who have twins know, this is about when things start to get easier. The fog lifts and you start to get a life back. I am getting close to completing my work on the next version of LabVIEW. That means I should have more time to post here.&lt;br /&gt;&lt;br /&gt;Its the little touches that make the Mac OS a pleasure to use. Since I joined the LabVIEW team back in the LabVIEW 7.0 days, I have tried to add a little special Mac something to the release. Unfortunately, due to several circumstances, I will not be able to do that for the next release of LabVIEW.&lt;br /&gt;&lt;br /&gt;Stephen Covey, in his book &lt;a href="http://www.amazon.com/gp/redirect.html?ie=UTF8&amp;location=http%3A%2F%2Fwww.amazon.com%2FHabits-Highly-Effective-People%2Fdp%2F0743269519%3Fie%3DUTF8%26s%3Dbooks%26qid%3D1208789933%26sr%3D8-1&amp;tag=thefresoc-20&amp;linkCode=ur2&amp;camp=1789&amp;creative=9325"&gt;The 7 Habits of Highly Effective People&lt;/a&gt;&lt;img src="http://www.assoc-amazon.com/e/ir?t=thefresoc-20&amp;amp;l=ur2&amp;amp;o=1" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /&gt; talks about sharpening the saw. In other words, stop every once in a while and evaluate your efficiency and take some time to become more efficient. We are doing that with the Mac build of LabVIEW, which means the next release will not have the bells and whistles I would like to have in it.&lt;br /&gt;&lt;br /&gt;To lament this, I wanted to publicly remind myself of the cool little Mac features I have been able to  get into LabVIEW since 7.0. I hope there are also some things in here that you didn't know, and can now be more productive in LabVIEW. (Warning: These features are currently Mac only. Using LabVIEW on Windows may get frustrating after getting used to these features on a Mac.)&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Go To LabVIEW Folder&lt;/span&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_103x98gpMb0/SAygkGIAhJI/AAAAAAAAAB8/MHYyWqoLWaI/s1600-h/GoToLabVIEWFolder.png"&gt;&lt;img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;" src="http://3.bp.blogspot.com/_103x98gpMb0/SAygkGIAhJI/AAAAAAAAAB8/MHYyWqoLWaI/s400/GoToLabVIEWFolder.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5191701012431275154" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;I was fixing a problem with the file dialog box, when I started to get annoyed with trying to find the LabVIEW folder of the LabVIEW I was currently running (I have several versions of LabVIEW scattered all over my hard drive). So I added a button to the Open File dialog (if it treats LLBs as folders) that will allow you to go directly to the currently running LabVIEW's folder.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Horizontal Scrolling&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;LabVIEW supported the scroll wheel on the mouse on Windows before it was supported on the Mac. One day I got very annoyed that the scroll wheel did nothing in LabVIEW on the Mac, so I added scroll wheel support. Now that only brought us on parity with Windows, so I went a step further and added horizontal scrolling and fast scrolling. When the Mighty Mouse came out, LabVIEW worked in all directions. However, if you do not have a Mighty Mouse, you can scroll horizontally by holding down the shift key and using the scroll wheel. Fast Scrolling support is enabled (horizontal and vertical) by holding down  the option key. It will double the scroll speed.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;LabVIEW Version on Dock Icon&lt;/span&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_103x98gpMb0/SAymsWIAhKI/AAAAAAAAACE/f0cHeFfqscg/s1600-h/BadgeAppInDock.png"&gt;&lt;img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;" src="http://4.bp.blogspot.com/_103x98gpMb0/SAymsWIAhKI/AAAAAAAAACE/f0cHeFfqscg/s400/BadgeAppInDock.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5191707751234962594" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Note: This appears not to be compatible with Leopard. I don't know that this will be fixed in time for the next release.&lt;br /&gt;&lt;br /&gt;If you set "BadgeAppInDock: True" in your LabVIEW preferences file, the version of LabVIEW will show up on the LabVIEW icon in the dock after you launch (you may have to click on it for it to show up). I never got it working quite right (and apparently it doesn't work for Leopard) so we left it in behind a preference setting. The version number on the icon should survive LabVIEW quit, however, it will be cleared after the Dock is restarted.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Flexible Preference File Format&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The "style" of preference files for LabVIEW varies between the platforms. For instance, Windows has a "key=value" format and the Mac has a "key: value" format. I made the Mac preferences file format much more flexible, so line endings don't matter (DOS, Mac Classic or UNIX line endings will work), and equals (=) and colon (:) will work. By default, LabVIEW on Mac will write out the "key: value" format, but can read either format.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Command Line Path Strings&lt;/span&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_103x98gpMb0/SAyosWIAhLI/AAAAAAAAACM/thdyA7SWQmc/s1600-h/CommandLinePaths.png"&gt;&lt;img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;" src="http://4.bp.blogspot.com/_103x98gpMb0/SAyosWIAhLI/AAAAAAAAACM/thdyA7SWQmc/s400/CommandLinePaths.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5191709950258218162" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;This isn't really a Mac specific feature, its more of a Mac necessitated workaround. I added two VIs at &lt;vilib&gt;/AdvancedString: Command Line String To Path.vi and Path To Command Line String.vi. These VIs look and behave very similar to String to Path and Path to String primitives, and are drop in replacements for them. In fact, on every other platform, they behave exactly the same as their primitive counterparts. On the Mac, however, they convert between Mac classic paths (colon separated) and UNIX paths (slash separated).&lt;br /&gt;&lt;br /&gt;The diagram shown here can convert symlinks into the path they represent (the Get File Info primitive does this a lot better). Notice the pink on the Path/String conversion bullets. They are the AdvancedString versions.&lt;br /&gt;&lt;br /&gt;Use these VIs whenever you are interacting with the command line. This will make your VIs more portable among platforms.&lt;br /&gt;&lt;br /&gt;I know I am forgetting a few other features, but these are the ones that have remained in my memory after my year of no sleep.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19928387-5604611064472492427?l=themacview.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://themacview.blogspot.com/feeds/5604611064472492427/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19928387&amp;postID=5604611064472492427' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19928387/posts/default/5604611064472492427'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19928387/posts/default/5604611064472492427'/><link rel='alternate' type='text/html' href='http://themacview.blogspot.com/2008/04/its-little-things.html' title='Its The Little Things'/><author><name>Marc Page</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-KXZHHLyZcGU/AAAAAAAAAAI/AAAAAAAAJuU/PGlqPNBP9l4/s512-c/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_103x98gpMb0/SAygkGIAhJI/AAAAAAAAAB8/MHYyWqoLWaI/s72-c/GoToLabVIEWFolder.png' height='72' width='72'/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-19928387.post-5833428885813703662</id><published>2007-08-16T08:15:00.001-07:00</published><updated>2008-11-12T21:57:19.840-08:00</updated><title type='text'>Taking advantage of mutliple CPUs</title><content type='html'>There has been a lot of talk recently about how difficult it is in C/C++ to write good code that efficiently takes advantage of multiple cores/CPUs. That is one of the inherent benefits of LabVIEW, it will automatically split things out onto multiple cores/CPUs if it can figure out that it can.&lt;br /&gt;&lt;br /&gt;In the NI-Week keynote, they demonstrated a block diagram with four for-loops executing simultaneously. That is one way to do it. It is simple and gets the job done. However, sometimes you need something that is a little more flexible. To do this, you can use Queues and Open VI by Reference.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://2.bp.blogspot.com/_103x98gpMb0/RsRrfSryGfI/AAAAAAAAAAw/g5aCuNoENCY/s1600-h/Spawn+VI.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/_103x98gpMb0/RsRrfSryGfI/AAAAAAAAAAw/g5aCuNoENCY/s400/Spawn+VI.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5099318863425837554" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;This block diagram shows a VI I wrote that generalizes and simplifies the task of running a VI multiple times simultaneously on different sets of data. It takes a path to the VI to run several copies of, two queue references, the names of the queue controls on the VI and the number of copies to start running.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://4.bp.blogspot.com/_103x98gpMb0/RsRs0yryGgI/AAAAAAAAAA4/SvNV8HAgUjE/s1600-h/Worker.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://4.bp.blogspot.com/_103x98gpMb0/RsRs0yryGgI/AAAAAAAAAA4/SvNV8HAgUjE/s400/Worker.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5099320332304652802" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Here is an example of the worker VI. All it takes is two queues, the Data In Queue and the Data Out Queue. It takes a unit of work from the Data In Queue, works on it and puts the results in the Data Out Queue. You may recognize the work being done as the for loop work done in the NI-Week Keynote.&lt;br /&gt;&lt;br /&gt;There are, of course, some caveats to great performance and working as expected.&lt;br /&gt;&lt;br /&gt;1. Each unit of work must be independent. It may not rely on any other unit of work.&lt;br /&gt;&lt;br /&gt;2. There must be no references to uninitialized shift registers, global VIs or references to things that are not protected against being called from multiple threads.&lt;br /&gt;&lt;br /&gt;3. The worker VI (and as many sub VIs as possible) must be Reeantrant (File -&gt; VI Properties -&gt; Execution).&lt;br /&gt;&lt;br /&gt;4. The Units of work must be fairly hefty. You must have significantly more work done in the VI than the overhead of passing things around in queues.&lt;br /&gt;&lt;br /&gt;Using the VI in the keynote on my Mac Pro (4 core), I got 3.6x faster than single core. When I replaced it with the VIs shown above doing the work, I got to 4.9x.&lt;br /&gt;&lt;br /&gt;Also of note: on the Mac, you can determine the number of cores in the machine by running the VI at vi.lib/Platform/Miscellaneous.llb/MPProcessors.vi.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19928387-5833428885813703662?l=themacview.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://themacview.blogspot.com/feeds/5833428885813703662/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19928387&amp;postID=5833428885813703662' title='8 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19928387/posts/default/5833428885813703662'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19928387/posts/default/5833428885813703662'/><link rel='alternate' type='text/html' href='http://themacview.blogspot.com/2007/08/taking-advantage-of-mutliple-cpus.html' title='Taking advantage of mutliple CPUs'/><author><name>Marc Page</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-KXZHHLyZcGU/AAAAAAAAAAI/AAAAAAAAJuU/PGlqPNBP9l4/s512-c/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_103x98gpMb0/RsRrfSryGfI/AAAAAAAAAAw/g5aCuNoENCY/s72-c/Spawn+VI.png' height='72' width='72'/><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-19928387.post-1068210604407837856</id><published>2007-06-26T07:15:00.000-07:00</published><updated>2007-06-26T08:20:38.794-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Computers'/><category scheme='http://www.blogger.com/atom/ns#' term='ZFS'/><category scheme='http://www.blogger.com/atom/ns#' term='Macintosh'/><category scheme='http://www.blogger.com/atom/ns#' term='Mac'/><category scheme='http://www.blogger.com/atom/ns#' term='LabVIEW'/><category scheme='http://www.blogger.com/atom/ns#' term='File Systems'/><category scheme='http://www.blogger.com/atom/ns#' term='Coding'/><category scheme='http://www.blogger.com/atom/ns#' term='Mac OS X'/><title type='text'>What ZFS support means</title><content type='html'>There have been a lot of ramblings about ZFS support in Leopard. Many people have wondered what the big deal is, and how it would help the average Mac user. Personally, I was just waiting for Steve Jobs to say the words "boot ZFS" and my life would have been compelte (well, not really, but it would have been pretty cool).&lt;br /&gt;&lt;br /&gt;First, a little history (as I remember it, so it may not be completely accurate, but its close enough). The first filesystem (the way files are stored on disk) on the Macintosh was MFS (Multiple File System). MFS was very short lived (I have never actually used it, just heard about it). It did not have hierarchical file system (no folders). HFS (Hierarchical File System) replaced MFS pretty quickly. HFS was written when most people still booted off of 3.5" floppy disks (1.44 MB max) and computer RAM was measured in kB not GB. Then Apple upgraded HFS to HFSPlus. It handled much bigger drives, supported Unicode better and was just overall a better, more modern filesystem. The last little tweak Apple did to HFSPlus was to add journalling support (the filesystem better handled unexpected power outages).&lt;br /&gt;&lt;br /&gt;The Sun develops an incredible filesystem, ZFS (Zetabyte File System). &lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;br /&gt;&lt;li&gt; &lt;b&gt;Adding more disk space is easy&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Right now, there are one or more logical disks for every physical disk. Most people are familiar with Macintosh HD which is a logical disk (Macintosh HD on the desktop) and a physical disk (say, a Western Digital inside their Mac). You can partition a physical disk into multiple logical disks. I have done this with a 250 GB external firewire drive. I have a different Mac OS version on each of (now 5) partitions, or logical disks.&lt;br /&gt;&lt;br /&gt;ZFS takes that trend in the reverse direction. You can have multiple physical disks "pooled" together into one logical disk. Imagine the following: you are running out of disk space, so you buy a new, much bigger hard drive. You install it and format it, and now you have two options: (1) migrate everything to the new drive, or (2) do some UNIX command lines to hobble the new disk into the filesystem on the old disk (sym-links, moving the home directory, etc). Neither of these is very clean, and both make things feel like the system is fragile.&lt;br /&gt;&lt;br /&gt;If your main hard drive had been formatted ZFS, you could do the following instead: Tell the OS to add the new drive to the "pool" of drive space available. That's it. The logical disk, Macintosh HD on your desktop, would now have the full storage capacity of both physical disks in your system. You can add as many drives as you can connect to your machine.&lt;br /&gt;&lt;br /&gt;&lt;li&gt; &lt;b&gt;Speed benefits of RAID, but in a simpler package&lt;/b&gt;&lt;br&gt;&lt;br /&gt;&lt;br /&gt;The idea of "pooling" physical disks together for the logical disk has another benefit that is similar to the speed concepts in RAID. When you write data, you split the data between multiple disks. Then when you read it, both disks work as fast as they can to get their piece of the data requested. This is similar in concept to multiple CPUs (cores) in Macs today. If you can have two or more things sharing the load, you can make it faster.&lt;br /&gt;&lt;br /&gt;&lt;li&gt; &lt;b&gt;Failing disks can be detected sooner&lt;/b&gt;&lt;br&gt;&lt;br /&gt;&lt;br /&gt;The problem with using multiple disks, is that your risk of disk failure goes up dramatically. Instead of a 5% that one disk will fail, you have a 10% chance that one of the two disks will fail (ok, I don't remember my statistics, or at least didn't want to think too hard about it, but you get the idea). Some RAID schemes solve this problem by storing just enough shared data on the disks, that if one drive goes down, it can continue to give you correct data (although slower) until you replace the drive.&lt;br /&gt;&lt;br /&gt;ZFS has a RAID mode, but you have to have all the disks be the same size. Standard ZFS has a cool feature though. Every block of data that is written, has a checksum written with it. Every time a block is read, it checks to make sure that checksum is correct. As soon as it finds a bad block, you can tell it to remove the bad disk from the "pool" (which will copy the data onto the remaining disks) and then replace the bad disk. You get very early detection of a failing disk, and should lose less data.&lt;br /&gt;&lt;br /&gt;&lt;li&gt; &lt;b&gt;Compression is built into the filesystem&lt;/b&gt;&lt;br&gt;&lt;br /&gt;&lt;br /&gt;&lt;strike&gt;Back in the dark days&lt;/strike&gt; Back when I used a PC and DOS, there was a cool program called Stacker (later Microsoft had a very similar feature). It allows you to reformat a disk and use compression to get more disk space. ZFS brings this back.&lt;br /&gt;&lt;br /&gt;With ZFS, you can turn compression on or off at any moment. While it is on, any data written to disk will be compressed. When off, data is written in raw, uncompressed format. When reading, it will read whatever format was written, compressed or uncompressed.&lt;br /&gt;&lt;br /&gt;You may thing that adding compression would slow down the filesystem, but it actually speeds it up. Processor and memory speeds have been growing at a much faster pace than disk speeds. So the little bit of time it takes to compress/uncompress the data is nothing compared to the time it takes the disk to read or write the data.&lt;br /&gt;&lt;br /&gt;&lt;li&gt; &lt;b&gt;Entire "Disk" revision history available&lt;/b&gt;&lt;br&gt;&lt;br /&gt;&lt;br /&gt;ZFS has a feature called snapshots. This allows you to create a special "directory" (really a file) that is a snapshot of the filesystem at that moment in time. Think of it as a live, whole system Time Machine, without the external disk.&lt;br /&gt;&lt;br /&gt;This snapshot "directory" takes next to no time to create (there's nothing to copy), and takes up very minimal space. Basically, whenever you modify a file, the old one is kept in the snapshot. Any files that have not been changed since the snapshot are shared between the two. Its kind of like a whole filesystem diff.&lt;br /&gt;&lt;br /&gt;Imagine working on a project, and you get to a cross-road. A decision on direction is needed. You choose what you think is the best direction, but want to get back to the point your at in your project just in case. The code may not be to a point that you can put it in source code control, so you right click on the folder and select Create an Archive and make a zip file of the "snapshot". If it is a large project, you go to lunch and come back just as it finishes archiving it. You continue on and then realize that it is not the direction you really wanted to go. You unzip your snapshot zip file (again, going to lunch), and only then realize that you missed some files in another folder.&lt;br /&gt;&lt;br /&gt;With ZFS, just take regular snapshots of the entire filesystem. They are quick, small and capture the state of the entire filesystem.&lt;br /&gt;&lt;br /&gt;&lt;B&gt;NOTE:&lt;/B&gt; Snapshots are not a replacement for backups. If your system gets fried, you lose your snapshots and your data. Backups, like with Time Machine, are extremely valuable and everyone should have a backup strategy.&lt;br /&gt;&lt;br /&gt;&lt;/ol&gt;&lt;br /&gt;&lt;br /&gt;So what is Apple's plan with ZFS? Nobody but Apple (maybe even Steve Jobs) really knows, but here is what we do know. Leopard has had some limited support for ZFS. They are stated that Leopard has "read only" support for ZFS (at least the beta the just handed out at WWDC has read only ZFS). MacRumors has posted that Apple is giving developers a beta of read-write ZFS as a separate download.&lt;br /&gt;&lt;br /&gt;What I am looking forward to is when Apple replaces Journaled HFSPlus with ZFS as the default filesystem. That means they still need a non-beta read-write filesystem that you can boot Mac OS X off of (booting of ZFS is a fairly new feature on any OS).&lt;br /&gt;&lt;br /&gt;So I hope the clamor for ZFS grows and Apple listens. I love HFSPlus, but I have a feeling I would love ZFS a whole lot more.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19928387-1068210604407837856?l=themacview.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://themacview.blogspot.com/feeds/1068210604407837856/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19928387&amp;postID=1068210604407837856' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19928387/posts/default/1068210604407837856'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19928387/posts/default/1068210604407837856'/><link rel='alternate' type='text/html' href='http://themacview.blogspot.com/2007/06/what-zfs-support-means.html' title='What ZFS support means'/><author><name>Marc Page</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-KXZHHLyZcGU/AAAAAAAAAAI/AAAAAAAAJuU/PGlqPNBP9l4/s512-c/photo.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-19928387.post-7755311728761443425</id><published>2007-06-15T08:06:00.000-07:00</published><updated>2008-11-12T21:57:20.264-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Computers'/><category scheme='http://www.blogger.com/atom/ns#' term='Macintosh'/><category scheme='http://www.blogger.com/atom/ns#' term='Mac'/><category scheme='http://www.blogger.com/atom/ns#' term='LabVIEW'/><category scheme='http://www.blogger.com/atom/ns#' term='Good Code'/><category scheme='http://www.blogger.com/atom/ns#' term='Coding'/><category scheme='http://www.blogger.com/atom/ns#' term='Mac OS X'/><category scheme='http://www.blogger.com/atom/ns#' term='Documentation'/><title type='text'>The Importance of Documentation</title><content type='html'>Sorry for the long delay in posting. Between my three-year-old twin boys, three-month-old twin girls and working hard on getting the next version of LabVIEW for the Mac in great shape, I've been a bit busy.&lt;br /&gt;&lt;br /&gt;I've noticed recently what a difference it makes having polished VIs. By polished, I mean well documented, consistent connector panes and a general overall consistency. With all the dialogs to get at the various information and set documentation on controls/indicators and VIs it can be a bit time consuming and difficult to make sure everything is consistent, but it is worth it.&lt;br /&gt;&lt;br /&gt;In 8.2.1, you not longer use Command-H to show/hide the contextual help window (which is the system Hide LabVIEW command), you use the Help key (or if you have a MacBook, Command-Shift-H). The contextual help window is your guide to understanding code on the block diagram.&lt;br /&gt;&lt;br /&gt;So the places to document your VI are:&lt;br /&gt;&lt;br /&gt;1. File -&gt; VI Properties -&gt; Documentation&lt;br /&gt;&lt;br /&gt;Set the VI description to some helpful text on what the VI does and how to use it. Also create an HTML file for further documentation. You can have just one HTML file and use anchors &amp;lt;a name="test"&amp;gt; for each VI. The Help tag is the name of the anchor. (NOTE: as of 8.2.1, you must manually escape any spaces in the anchors/Help tags, for instance &amp;lt;a name="test me"&amp;gt; would have a help tag of "test%20me").&lt;br /&gt;&lt;br /&gt;While you are in VI Properties, visit the following pages also:&lt;br /&gt;&lt;br /&gt;- Protection: make sure the password protection/locking is how you want it.&lt;br /&gt;- Execution: make sure Allow debugging and Enable automatic error handling are turned off (if desired).&lt;br /&gt;- Window Appearance: Make sure the window title is what you want it to be&lt;br /&gt;&lt;br /&gt;2. Right-click (control-click if you don't have a mighty mouse) on each control/indicator that is in the connector pane (and possibly others) and select Properties -&gt; Documentation and make sure the description is meaningful, as well as a short description in the tip strip. Also Right-click on each control/indicator in the connector pane and make sure that its Required/Recommended/Optional is set correctly. Also make sure that all controls and indicators that you meant to have on the connector pane are there.&lt;br /&gt;&lt;br /&gt;You probably want to visit similar controls/indicators on each VI, instead of visiting each control/indicator on a single VI. For instance, visit all the "error in (no error)" controls on all your VIs, to make sure they are named the same and have the same (or consistent) descriptions, then go on to "error out" and any other common data types. The idea is to make sure you are consistent.&lt;br /&gt;&lt;br /&gt;3. Right-click on the following elements of your Project window and select Properties:&lt;br /&gt;&lt;br /&gt;- Project Node (My Project.lvproj)&lt;br /&gt;- Library Nodes (MyLib.lvlib)&lt;br /&gt;- Class Nodes (MyClass.lvclass)&lt;br /&gt;etc.&lt;br /&gt;&lt;br /&gt;Go to the Documentation page (in the project case, its the Project Description) and fill in the information in a similar way.&lt;br /&gt;&lt;br /&gt;Doing this has three benefits:&lt;br /&gt;&lt;br /&gt;1. The next person who needs to modify the project (or you in 6 months) will have plenty of documentation on how it works and how to use it.&lt;br /&gt;&lt;br /&gt;2. If you product is meant to be used by other LabVIEW developers (a library or class meant for other to use) will have an easier time learning how to use your code correctly.&lt;br /&gt;&lt;br /&gt;3. While you document you code, you find things you missed. It forces you to think through how things actually work, and helps you find problems or missing elements.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://1.bp.blogspot.com/_103x98gpMb0/RnLDG_IJTSI/AAAAAAAAAAc/W2cOFl55gJA/s1600-h/Picture+1.png"&gt;&lt;img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;" src="http://1.bp.blogspot.com/_103x98gpMb0/RnLDG_IJTSI/AAAAAAAAAAc/W2cOFl55gJA/s320/Picture+1.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5076334254792199458" /&gt;&lt;/a&gt;&lt;br /&gt;To simplify the documentation of VIs (not other project items like classes and libraries), I have written a tool that walks through all the VIs in a project and allows you to see in one place all of the VI information and allows you to update it in one place.&lt;br /&gt;&lt;br /&gt;As you can see by clicking on the image to the right, you can easily navigate through all VIs in a project, and all terminals in a VI. You can also connect/disconnect terminals, rename terminals, add documentation to terminals and VIs, set the window title, set debugging and auto error handling and see how it all fits together in one screen.&lt;br /&gt;&lt;br /&gt;If you are interested in trying out this tool, you can email me at Marc dot Page at NI dot com, and I will reply with a zip file containing this tool.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19928387-7755311728761443425?l=themacview.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://themacview.blogspot.com/feeds/7755311728761443425/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19928387&amp;postID=7755311728761443425' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19928387/posts/default/7755311728761443425'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19928387/posts/default/7755311728761443425'/><link rel='alternate' type='text/html' href='http://themacview.blogspot.com/2007/06/importance-of-documentation.html' title='The Importance of Documentation'/><author><name>Marc Page</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-KXZHHLyZcGU/AAAAAAAAAAI/AAAAAAAAJuU/PGlqPNBP9l4/s512-c/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_103x98gpMb0/RnLDG_IJTSI/AAAAAAAAAAc/W2cOFl55gJA/s72-c/Picture+1.png' height='72' width='72'/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-19928387.post-7650540019042400583</id><published>2007-01-19T08:52:00.000-08:00</published><updated>2008-11-12T21:57:20.571-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Computers'/><category scheme='http://www.blogger.com/atom/ns#' term='Macintosh'/><category scheme='http://www.blogger.com/atom/ns#' term='Mac'/><category scheme='http://www.blogger.com/atom/ns#' term='Steve Jobs'/><category scheme='http://www.blogger.com/atom/ns#' term='Market Share'/><category scheme='http://www.blogger.com/atom/ns#' term='Mac OS X'/><title type='text'>The Revolution WILL be televised</title><content type='html'>Apple &lt;strike&gt;Computer&lt;/strike&gt; announced $1 billion profit on over $7 billion in revenue. IDC announced Apple's computer market share went up almost 30% year-on-year (now 4.7%). With all the buzz of the iPhone and iPod line, and Apple dropping the "Computer" from its name, some of us Mac fans are left to wonder what this all means.&lt;br /&gt;&lt;br /&gt;The iPod went from zero to hero in no time, and they continue to grow. The holiday quarter 2006 saw 50% more iPods being sold than the same quarter 2005. With AppleTV, iPhone and iPod Apple gets a lot of buzz, but its the Macintosh that is most interesting here. I think there is a quiet revolution happening.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://3.bp.blogspot.com/_103x98gpMb0/RbD7W0Qpd7I/AAAAAAAAAAM/qegeNgBRPFk/s1600-h/bell_curve3.gif"&gt;&lt;img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;" src="http://3.bp.blogspot.com/_103x98gpMb0/RbD7W0Qpd7I/AAAAAAAAAAM/qegeNgBRPFk/s320/bell_curve3.gif" border="0" alt=""id="BLOGGER_PHOTO_ID_5021789953922267058" /&gt;&lt;/a&gt;A popular book here at National Instruments is &lt;a href="http://en.wikipedia.org/wiki/Crossing_the_Chasm"&gt;Crossing the Chasm&lt;/a&gt;. In this book, the author discusses a &lt;a href="http://www.jonathanboutelle.com/mt/archives/2004/05/crossing_the_ch.html"&gt;Technology Adoption Model&lt;/a&gt; (image at link shown here) that is very helpful in understanding future directions in technology.&lt;br /&gt;&lt;br /&gt;The theory goes like this:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Innovators are always on the bleeding edge in accepting new technology&lt;br /&gt;&lt;li&gt;Early Adopters quickly follow the Innovators&lt;br /&gt;&lt;li&gt;If the Early Majority accepts the new technology, then Late Majority will shortly follow&lt;br /&gt;&lt;li&gt;There are always Laggards that are the last to accept the new technology&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;The Macintosh never really got past the Early Adopters phase. That is the "chasm" referred to in the book. The iPod showed that Apple &lt;i&gt;could&lt;/i&gt; cross that chasm. With one win under their belt, I think the iPhone and AppleTV are the next tests of their new model. But what about the Macintosh.&lt;br /&gt;&lt;br /&gt;Another technology adoption model is the &lt;a href="http://www.ventureblog.com/articles/indiv/2003/000070.html"&gt;Alpha Geek&lt;/a&gt; model. This model states that when a majority of Alpha Geeks adopt a technology, the rest public at large will eventually follow. I think the IBM PC is a good example of this.&lt;br /&gt;&lt;br /&gt;In the mid 80's home computers became popular. You had the Atari, Commodore, TRS, IBM, Amiga and Apple camps. The Alpha Geeks we split among them all. So when people asked their Alpha Geek friend which computer to buy, the advice depended on who your Alpha Geek was. Then as the PC became more popular among Alpha Geeks, their advice started converging on the PC, thus a shift in the Alpha Geek preference multiplied the effect on the general population.&lt;br /&gt;&lt;br /&gt;Ten years ago, if you were to poll Alpha Geeks you would have found that 90% to 95% of them used Microsoft Windows. Anecdotal evidence over the last 10 years leads me to believe that another shift in Alpha Geek preference is happening, towards the Macintosh.&lt;br /&gt;&lt;br /&gt;I started to notice a change on &lt;a href="slashdot.org"&gt;Slashdot&lt;/a&gt; about the time Mac OS X was released. Slashdot ten years ago seemed to be more Linux oriented. Since then more and more posts were Apple related. Not only that, the posts became increasingly pro Apple.&lt;br /&gt;&lt;br /&gt;When I started working for National Instruments in 1997, there were just a handful of people who I worked with who had a Mac at home, and they were very, what we called at the time, Apple Evangelistas. Within the last few years, I have noticed that the developers I work with are starting to buy Macs for home use. Even more surprising is that the developers who are buying Macs are not Mac zealots. They are people who have been working on Windows versions of LabVIEW or DAQ, and really don't have much exposure to the Mac other than casual exposure. In fact, just this morning, another developer who I never thought would buy a Mac came up to me and said, "I have a MacBook Pro in my cart at the Apple store, and before I submitted the order, I just wanted to ask you about one of the features."&lt;br /&gt;&lt;br /&gt;The third anecdote comes from my personal history. I was an IBM PC guy in high school (DOS days). I had even (ignorantly) talked a friend into being anti-Mac (his family was trying to decide between Mac and PC at the time). Then I started working for the Navy. They had me working on  a Macintosh, and I grew to love it. However, this made me a geek black sheep of sorts in my family. My father tried to convince me that a Sparc station (from Sun) would be a better alternative to Microsoft.&lt;br /&gt;&lt;br /&gt;When I went off to college, my parents bought me a Compaq PC (sometimes I think it was for fear that I might buy a Mac at college). I used the computer for about a year and a half. It was a useful tool, and it was free (for me). Then  I got married. I was frustrated that my new wife had such a difficult time using our home computer. We decided it was time to sell the PC and get a Mac. Since then, I've purchased 6 Macs, and got my mother-in-law 2 Macs.&lt;br /&gt;&lt;br /&gt;I was still a geek black sheep in my family. My two brothers were Windows/Linux fans. None of the male members of my immediate family had anything good to say about the Macintosh. Well, at least until the Mac switched to Intel. I was floored when my father and two brothers, and different times, expressed that they would consider buying a Mac.&lt;br /&gt;&lt;br /&gt;I think that in the next ten years, we are going to see a personal computer revolution, and it WILL be televised (at least web-cast).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19928387-7650540019042400583?l=themacview.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://themacview.blogspot.com/feeds/7650540019042400583/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19928387&amp;postID=7650540019042400583' title='8 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19928387/posts/default/7650540019042400583'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19928387/posts/default/7650540019042400583'/><link rel='alternate' type='text/html' href='http://themacview.blogspot.com/2007/01/revolution-will-be-televised.html' title='The Revolution WILL be televised'/><author><name>Marc Page</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-KXZHHLyZcGU/AAAAAAAAAAI/AAAAAAAAJuU/PGlqPNBP9l4/s512-c/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_103x98gpMb0/RbD7W0Qpd7I/AAAAAAAAAAM/qegeNgBRPFk/s72-c/bell_curve3.gif' height='72' width='72'/><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-19928387.post-5142706345169651049</id><published>2006-12-07T15:50:00.000-08:00</published><updated>2006-12-07T13:34:18.436-08:00</updated><title type='text'>Presentation Mode for LabVIEW</title><content type='html'>Sorry for the delay in posting. I have several partial articles ready to go, just no time to flush them out (Busy on the next version of LabVIEW, plus my wife and I are expecting twin girls!).&lt;br /&gt;&lt;br /&gt;Have you ever used LabVIEW for a presentation, and you had to go in and increase the font size and make things generally bigger so that it was easier to see what was going on. Or maybe you needed to zoom out so you could fit the entire block diagram on the screen (naughty VI writer, all block diagrams should fit on a 17" LCD). Mac OS X 10.4 (Tiger) has a great way to "zoom" any application.&lt;br /&gt;&lt;br /&gt;Open a terminal (/Applications/Utilities/Terminal.app) and type:&lt;br /&gt;&lt;br /&gt;defaults write com.ni.LabVIEW AppleDisplayScaleFactor -string "2"&lt;br /&gt;&lt;br /&gt;That will make everything bigger, great for presentations. To shrink everything type:&lt;br /&gt;&lt;br /&gt;defaults write com.ni.LabVIEW AppleDisplayScaleFactor -string "0.5"&lt;br /&gt;&lt;br /&gt;You can use any scaling factor you want, and it only affects LabVIEW. To change it back to the way it was, type:&lt;br /&gt;&lt;br /&gt;defaults write com.ni.LabVIEW AppleDisplayScaleFactor -string "1"&lt;br /&gt;&lt;br /&gt;This can have unexpected sizing of the menu bar, but mousing around a bit usually fixes it (not all of the kinks in Apple's code have been worked out).&lt;br /&gt;&lt;br /&gt;Another method of zooming in that affects all applications is Universal Access Zoom. Open System Preferences (Apple Menu -&gt; System Preferences ...) and choose Universal Access (System -&gt; Universal Access). Select the "Seeing" tab and turn Zoom on.&lt;br /&gt;&lt;br /&gt;Whenever you need to zoom in on something, press Command-Option-+ (it says =, but it is really the keys with a plus sign (+) on them, numeric keypad or next to delete). You can zoom to just about any level. To zoom out, press Command-Option-- (minus sign, either on the numeric keypad or next to =/+).&lt;br /&gt;&lt;br /&gt;This zooming can come in handy when you are trying to look at a mess of wires (naughty VI writer) and using a CRT (LCDs are crisp enough to see the wires well, in my opinion).&lt;br /&gt;&lt;br /&gt;Well, there you have it. Some handy tools in Mac OS X to make LabVIEW (or any app) zoom in or out.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19928387-5142706345169651049?l=themacview.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://themacview.blogspot.com/feeds/5142706345169651049/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19928387&amp;postID=5142706345169651049' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19928387/posts/default/5142706345169651049'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19928387/posts/default/5142706345169651049'/><link rel='alternate' type='text/html' href='http://themacview.blogspot.com/2006/12/presentation-mode-for-labview.html' title='Presentation Mode for LabVIEW'/><author><name>Marc Page</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-KXZHHLyZcGU/AAAAAAAAAAI/AAAAAAAAJuU/PGlqPNBP9l4/s512-c/photo.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-19928387.post-4960424646902309885</id><published>2006-08-17T08:06:00.000-07:00</published><updated>2006-08-17T08:30:32.363-07:00</updated><title type='text'>Multiple Ways to Interact with OS</title><content type='html'>I attended the presentation by Christphe Salzmann as NI-Week about the state of LabVIEW and the Mac. He reminded me that there are many ways to interact with the OS. I have been focusing on Call Library Function Nodes to call functions in frameworks like Carbon.&lt;br /&gt;&lt;ol&gt;&lt;br /&gt;   &lt;li&gt;Run AppleScript Code (vi.lib-&gt;Platform)&lt;br /&gt;   &lt;li&gt;System Exec (Connectivity-&gt;Libraries &amp; Executables)&lt;br /&gt;   &lt;li&gt;Open System Command Pipe (vi.lib/Platform/system.llb)&lt;br /&gt;   &lt;li&gt;Call Library Function Node (Connectivity-&gt;Libraries &amp; Executables)&lt;br /&gt;   &lt;li&gt;AppleEvent (Data Communication-&gt;Protocols-&gt;AppleEvent)&lt;br /&gt;&lt;/ol&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Run AppleScript Code&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;The great thing about the AppleScript is that it is fairly english like. For operations in the Finder, you can record actions with  Script Editor (/Applications/AppleScript) directly to AppleScript. You can even script the interface, for example, select a menu item.&lt;br /&gt;&lt;br /&gt;See the &lt;a href="http://en.wikipedia.org/wiki/AppleScript"&gt;wikipedia entry&lt;/a&gt; for more information.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;System Exec&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;With the System Exec VI, you can execute commands like you would in Terminal (/Applications/Utilities). Because of the UNIX underpinnings of Mac OS X, this can be a powerful utility. The most difficult part will be parsing the text output. Parse Regular Expression (Programming-&gt;String) and Split String, Normalize End Of Line, Join Strings and Escape String (all in vi.lib/AdvancedString) make parsing the text output of command line utilities easier.&lt;br /&gt;&lt;br /&gt;A great place to pick up interesting tidbits on command line utilities is &lt;a href="http://www.macosxhints.com/"&gt;Mac OS X Hints.com&lt;/a&gt;. As a matter of fact, Run AppleScript Code is just a System Exec to the osascript command line utility.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Open System Command Pipe&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;This is similar to the System Exec, except that you you get a reference to the standard output, standard input and standard error, and you can interact with those references while the command line program is running. Using pipes is an advanced feature and may not always work as you expected, but it can give you more flexibility when working with command line tools.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Call Library Function Node&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;This is the option I have been exploring the most in this blog. This allows you to get at just about anything you can do with Carbon and C.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;AppleEvent &lt;/b&gt;&lt;br /&gt;&lt;br /&gt;The AppleEvent VIs have been in LabVIEW a long time. I personally have never used them, but they can be pretty powerful and flexible. If you are familiar with AppleEvents, its a great tool. I personally prefer Run AppleScript Code, which will create all the AppleEvents for me from an English like script.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;If you can think of any other ways to interact with the OS in LabVIEW, please post them in the comments.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19928387-4960424646902309885?l=themacview.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://themacview.blogspot.com/feeds/4960424646902309885/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19928387&amp;postID=4960424646902309885' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19928387/posts/default/4960424646902309885'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19928387/posts/default/4960424646902309885'/><link rel='alternate' type='text/html' href='http://themacview.blogspot.com/2006/08/multiple-ways-to-interact-with-os.html' title='Multiple Ways to Interact with OS'/><author><name>Marc Page</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-KXZHHLyZcGU/AAAAAAAAAAI/AAAAAAAAJuU/PGlqPNBP9l4/s512-c/photo.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-19928387.post-115504041517623607</id><published>2006-08-08T08:20:00.000-07:00</published><updated>2006-08-08T07:43:40.166-07:00</updated><title type='text'>20th Anniversary LabVIEW 8.20 Released Today</title><content type='html'>Today, 8/8 at 8:20 am, National Instruments released the 20th Anniversary Edition was released, featuring native Object Oriented programming and support for Intel Macintosh machines.&lt;br /&gt;&lt;br /&gt;Other Headlines:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.ni.com/labview/"&gt;National Instruments LabVIEW 8.20 page&lt;/a&gt;&lt;br /&gt;&lt;a href="http://home.businesswire.com/portal/site/google/index.jsp?ndmViewId=news_view&amp;newsId=20060808005035&amp;newsLang=en"&gt;Business Wire Post&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.macminute.com/2006/08/08/ni-labview-update/"&gt;MacMinute&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19928387-115504041517623607?l=themacview.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://themacview.blogspot.com/feeds/115504041517623607/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19928387&amp;postID=115504041517623607' title='8 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19928387/posts/default/115504041517623607'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19928387/posts/default/115504041517623607'/><link rel='alternate' type='text/html' href='http://themacview.blogspot.com/2006/08/20th-anniversary-labview-820-released.html' title='20th Anniversary LabVIEW 8.20 Released Today'/><author><name>Marc Page</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-KXZHHLyZcGU/AAAAAAAAAAI/AAAAAAAAJuU/PGlqPNBP9l4/s512-c/photo.jpg'/></author><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-19928387.post-115333398747640420</id><published>2006-07-19T11:11:00.000-07:00</published><updated>2006-07-19T11:49:59.326-07:00</updated><title type='text'>Finishing Up Next LabVIEW Version</title><content type='html'>It's been too long since I last posted. Getting LabVIEW ready to release is a big job.&lt;br /&gt;&lt;br /&gt;This release has been challenging for me since our Mac resources are being used to fix and validate LabVIEW on two different processors for the Mac. The good thing is that it has been a pretty smooth transition to MacIntel systems. Some parts of the code date back to the mid 80's, so we had to track down all the assumptions about what Endian we were using. We just fixed another issue along these lines in the last week (minor UI issue). We probably have a few more that we haven't caught, but there doesn't appear to be any huge issues.&lt;br /&gt;&lt;br /&gt;Running LabVIEW native on an Intel iMac is nice. They are very fast machines. It is noticeably faster than LabVIEW running on my Dual 1.8 G5 machine. I am really looking forward to working with this version of LabVIEW on an Intel machine on a regular basis.&lt;br /&gt;&lt;br /&gt;This next version of LabVIEW has also had some performance tweaking, so compared to 8.0, this next version "feels" faster. Launching LabVIEW is noticeably faster. One of the beta testers noticed that when you close the Getting Started window that LabVIEW quit, which is not standard behavior on a Mac. We changed that so that now it just closes the window. This makes "second launch" (clicking on the dock icon) much faster, since we are not launching LabVIEW.&lt;br /&gt;&lt;br /&gt;There is another Mac issues that most long time LabVIEW developers will run into. We changed Command-H to the standard Hide Application instead of Show Context Help. That means that most people who are in the habit of pressing Command-H for Context Help will suddenly have their LabVIEW disappear. The new keystroke is Command-Shift-H. Unfortunately this key sequence does not work for older versions of LabVIEW, so if you switch back and forth (two different machines) changing your habit will not be as easy. If you have a full size keyboard (not a laptop keyboard) you can use the Help key (by Home, End, Page Up and Page Down) to toggle the Context Help window. That does work in all versions of LabVIEW.&lt;br /&gt;&lt;br /&gt;We do not have Universal VIs, so a VI will either be Mac-PowerPC or Mac-Intel, and will need to be recompiled when moved to the other platform. Since LabVIEW does the compiling behind the scenes, most people will not notice the difference for small hierarchies of VIs. The side affect is that when you launch for the first time on a MacIntel machine, you will be prompted to Mass Compile LabVIEW (convert the VIs in LabVIEW to Mac-Intel VIs). This is similar to the 8.0.1 Mass Compile, for those who remember that, but will be MUCH faster (we sped up the method of Mass Compiling, and you are on a very fast machine).&lt;br /&gt;&lt;br /&gt;For those who get LabVIEW Pro (or get the Application Builder add on to LabVIEW) there is a way to build Universal Binary applications and frameworks with LabVIEW. Since VIs are cannot be Universal, we pull some tricks in the build Application/Framework to have the capability there. I have submitted a Knowledge Base article that describes the process of creating a Universal LabVIEW Application/Framework.&lt;br /&gt;&lt;br /&gt;There are also some new features that I helped make sure they were on the Mac. I think all of them will be featured in the NI-Week keynote. Some of them go right along with some of the topics my blog.&lt;br /&gt;&lt;br /&gt;I'm very pleased with the stability and speed of LabVIEW on Intel Macs. I hope you are as pleased as well. If you are coming to NI-Week next month, hunt me down and lets chat. I love talking to LabVIEW and/or Mac users.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19928387-115333398747640420?l=themacview.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://themacview.blogspot.com/feeds/115333398747640420/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19928387&amp;postID=115333398747640420' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19928387/posts/default/115333398747640420'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19928387/posts/default/115333398747640420'/><link rel='alternate' type='text/html' href='http://themacview.blogspot.com/2006/07/finishing-up-next-labview-version.html' title='Finishing Up Next LabVIEW Version'/><author><name>Marc Page</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-KXZHHLyZcGU/AAAAAAAAAAI/AAAAAAAAJuU/PGlqPNBP9l4/s512-c/photo.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-19928387.post-114807187580663018</id><published>2006-05-19T13:25:00.000-07:00</published><updated>2006-05-19T14:29:52.456-07:00</updated><title type='text'>Quick Note After Wrapping Up Some LabVIEW Testing</title><content type='html'>I've just finished up a milestone on the next version of LabVIEW. Each release we polish up the Mac version a little more. It seems Apple is always keeping us busy with their constant changes (68k to PowerPC, Mac Classic to Mac OS X, PowerPC to x86). We still have another hurdle after we pass up the Intel transition. Apple is deprecating several APIs that we use in a lot of our code. We are slowly moving our model to be more compatible with the new APIs, and it looks like Apple is helping us make that transition sooner than we might have otherwise.&lt;br /&gt;&lt;br /&gt;The unfortunate thing is that these transitions take time away from our Mac LabVIEW improvements. We will still get a few Mac specific improvements in the next version, just not as many as I would have liked.&lt;br /&gt;&lt;br /&gt;On a completely unrelated note, I just looked at the information about visitors to this site, about you. I thought I would share some of the interesting tidbits about people visiting this blog.&lt;br /&gt;&lt;br /&gt;57% of the visits have been from the United States.&lt;br /&gt;Almost 8% of the visits have been from France (Bienvenue).&lt;br /&gt;Over 5% of the visits have been from Germany (Willkommen).&lt;br /&gt;Over 4% of the visits have been from the United Kingdom (Hallo).&lt;br /&gt;Over 3% of the visits have been from Canada (How's it going, eh?).&lt;br /&gt;&lt;br /&gt;The rest are from (in order): Switzerland, Netherlands, Japan, Italy, Belgium, Australia, India, Sweden, Norway, Austria, New Zealand, Spain, Ireland, Colombia, Finland, Slovenia, Mexico, Denmark, Portugal, Hungary, Taiwan, Poland, Russian Federation, Romania, Malaysia, Satellite Provider, Saudi Arabia, Korea, Republic of, Europe, Turkey, Georgia, Peru, Hong Kong, Chile, Czech Republic, Thailand, Cyprus and Bulgaria.&lt;br /&gt;&lt;br /&gt;The search terms people use to find this site are interesting too. &lt;br /&gt;&lt;br /&gt;LabVIEW is in 84% of the searches.&lt;br /&gt;43% contain Mac, Macintosh, MacOS or MacOSX&lt;br /&gt;31% contain Intel, Intel-based, Universal or Macintel.&lt;br /&gt;23% contain Array, Path, Struct, Structs, Structure, Structures, Pointer, Pointers, Pointeur or Cluster.&lt;br /&gt;15% contain 8 or 8.0.&lt;br /&gt;10% contain Carbon or Xcode.&lt;br /&gt;&lt;br /&gt;Another interesting tidbit is that it appears that some people are using Google to come back to this site (What was that blog about LabVIEW and the Mac again?) I would suggest that if you are reading this, go ahead and set a bookmark. Its a lot faster to get back here. Also, if you have an RSS aggregator (Safari has one built in) you can bookmark the RSS feed. Then you will know when a new article is posted.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19928387-114807187580663018?l=themacview.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://themacview.blogspot.com/feeds/114807187580663018/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19928387&amp;postID=114807187580663018' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19928387/posts/default/114807187580663018'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19928387/posts/default/114807187580663018'/><link rel='alternate' type='text/html' href='http://themacview.blogspot.com/2006/05/quick-note-after-wrapping-up-some.html' title='Quick Note After Wrapping Up Some LabVIEW Testing'/><author><name>Marc Page</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-KXZHHLyZcGU/AAAAAAAAAAI/AAAAAAAAJuU/PGlqPNBP9l4/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-19928387.post-114556694269414601</id><published>2006-04-20T13:56:00.000-07:00</published><updated>2006-04-20T14:02:22.703-07:00</updated><title type='text'>What are those .alias files?</title><content type='html'>The project files (.lvproj) in LabVIEW 8.0 are great. It is a great way to organize everything having to do with your "project." You can keep text files, Word doc files, PDF files, html files and all sorts of other stuff. Plus if you have LabVIEW Pro and you are building an application for framework, you have to use a project.&lt;br /&gt;&lt;br /&gt;So after a project is created, a .alias file shows up. What is this file? If you open the file in TextWrangler (or whatever your favorite text editor is), you will see that it contains text like:&lt;br /&gt;&lt;br /&gt;[My Computer]&lt;br /&gt;My Computer = "10.0.39.175"&lt;br /&gt;&lt;br /&gt;Ok, it has my IP address. What good is it. Well, on the Mac it isn't much good. You can pretty much delete them. You don't need to add them to source code control. On Windows, it keeps track of mappings between embedded targets and their IP addresses. Its kind of a DNS system of sorts.&lt;br /&gt;&lt;br /&gt;But for us Mac users, they are files to put up with. You can create a Folder Action to automatically delete .alias files in the folders of your interest. Since my AppleScript is a bit weak, I will leave that as an exercise for the reader.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19928387-114556694269414601?l=themacview.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://themacview.blogspot.com/feeds/114556694269414601/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19928387&amp;postID=114556694269414601' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19928387/posts/default/114556694269414601'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19928387/posts/default/114556694269414601'/><link rel='alternate' type='text/html' href='http://themacview.blogspot.com/2006/04/what-are-those-alias-files.html' title='What are those .alias files?'/><author><name>Marc Page</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-KXZHHLyZcGU/AAAAAAAAAAI/AAAAAAAAJuU/PGlqPNBP9l4/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-19928387.post-114321863561342776</id><published>2006-03-24T08:25:00.000-08:00</published><updated>2006-03-24T11:30:48.416-08:00</updated><title type='text'>Macintel and LabVIEW</title><content type='html'>I recently saw an article from a developer at Adobe about &lt;a href="http://blogs.adobe.com/scottbyer/2006/03/macintosh_and_t.html"&gt;Adobe's Macintosh and the Intel switch&lt;/a&gt;. I found myself nodding a lot reading the article. However, I think they are in this position because they did not listen to Apple.&lt;br /&gt;&lt;br /&gt;When we ported LabVIEW to Mac OS X (LabVIEW 7.0) we had several decisions to make. Should we keep LabVIEW CFM, or make it Mach-O (native binary format). CFM definitely would have been easier. It would have also given us a single binary that would work on Mac OS 9 and Mac OS X. We could have kept compiling with CodeWarrior (the IDE/Compiler of choice for many Mac developers at the time). It had a lot of advantages. If we would have gone with Mach-O, we would have access to new APIs and we would be following Apple's suggestions, but we would loose the fast compiler, excellent debugging environment and we would have to rebuild everything in Xcode (then ProjectBuilder).&lt;br /&gt;&lt;br /&gt;A wise senior Mac developer here in the LabVIEW group decided we should bite the bullet and follow Apple's suggestion. We would not get rid of the CodeWarrior build, so when MetroWerks was able to come up to Xcode's level of Mach-O, we could switch back (which never happened).&lt;br /&gt;&lt;br /&gt;LabVIEW has a very large Xcode project, so I feel the pain of the Adobe engineer. Xcode does not do well with large projects, although it has been making huge leaps in every release. Distributed compiles has made the slow compiles much more manageable. The editor is still slow. Link times will put you to sleep (zero link does not work well on large projects). It was painful, to say the least, but we did it because we trusted that Apple knew what they were talking about.&lt;br /&gt;&lt;br /&gt;Adobe, on the other hand, did not listen to Apple (or maybe Apple didn't tell them?). Now they are faced with converting over to Xcode and getting everything Macintel ready.&lt;br /&gt;&lt;br /&gt;There are a few things in LabVIEW that make it more difficult to port to another processor architecture. The biggest is probably that it is a compiler. When a VI is run, we compile the diagram to native code, and then run it. So for LabVIEW, it is not just a matter of recompiling, we actually have to change our code to compile native x86. One benefit we have, however, is the most of the hard work on that side was done with LabVIEW on Windows and Linux. All that was left was to massage the x86 code generator to follow Mac OS calling conventions, not trivial, but much easier than starting fresh on the compiler part.&lt;br /&gt;&lt;br /&gt;We of course found all sorts of Endian assumptions in Mac specific code, along with all the other minor things that all need to be cleaned up.&lt;br /&gt;&lt;br /&gt;The bottom line is that we listened to Apple and our transition is going pretty smooth. Adobe didn't and now they are paying the price.&lt;br /&gt;&lt;br /&gt;Now what got us is that Apple led us to believe that consumer hardware would not be available until summer. When they sprung a January release on us, we had already set our release schedules. I imagine that is also the case with Adobe and Microsoft. Any project of that scale would be difficult to port, and moving the schedule up six months really causes problems.&lt;br /&gt;&lt;br /&gt;Well, I just wanted to give another developer's perspective on the Macintel transition. I think this one is going very well, especially compared to the Mac OS 9 to Mac OS X transition.&lt;br /&gt;&lt;br /&gt;[Corrected a statement about Apple's timeline for transitioning to Intel hardware 2006-03-24 13:29pm CST]&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19928387-114321863561342776?l=themacview.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://themacview.blogspot.com/feeds/114321863561342776/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19928387&amp;postID=114321863561342776' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19928387/posts/default/114321863561342776'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19928387/posts/default/114321863561342776'/><link rel='alternate' type='text/html' href='http://themacview.blogspot.com/2006/03/macintel-and-labview.html' title='Macintel and LabVIEW'/><author><name>Marc Page</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-KXZHHLyZcGU/AAAAAAAAAAI/AAAAAAAAJuU/PGlqPNBP9l4/s512-c/photo.jpg'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-19928387.post-114321348100680828</id><published>2006-03-24T06:59:00.000-08:00</published><updated>2006-03-24T07:18:16.360-08:00</updated><title type='text'>Performance, Compatibility, Links and Aliases</title><content type='html'>I'd like to diverge a bit from the tips and tricks to talk a little about an issue I am running into in developing LabVIEW on Mac OS X. In the Mac OS Classic version of LabVIEW, we had a magic feature that would treat an alias anywhere in a path as transparent. This allowed you to move things around, replace the original with an alias and LabVIEW would treat the alias as the original item (folder or file).&lt;br /&gt;&lt;br /&gt;When Mac OS X came along, we switched to Apples newer Carbon APIs that allowed for long file names. We also had a new type of alias, called a symbolic link (UNIX form of alias). So now, if an alias or symbolic link were to be anywhere in the path, LabVIEW should just treat it as the original item.&lt;br /&gt;&lt;br /&gt;In LabVIEW 7.x, our first port of LabVIEW to Mac OS X, we found that we would handle symbolic links by accident, but aliases no longer worked. In LabVIEW 8.0, we added the ability to handle aliases as well, at a cost. Launch and Mass Compile, file intensive operations, were spending around 30% of their time in converting a path into a file system representation (FSRef). I reworked the code for the next major version of LabVIEW down to 7% to 9%. This has a noticeable impact on launch and mass compile, but I think we can do better.&lt;br /&gt;&lt;br /&gt;Here are the options I am weighing:&lt;br /&gt;&lt;br /&gt;1. By default, disable alias support (you can set a token in the preferences file to re-enable it).&lt;br /&gt;2. Change the path format to UNIX style instead of HFS Mac Classic style&lt;br /&gt;      UNIX: /Users/johnd/Desktop&lt;br /&gt;      HFS: Macintosh HD:Users:johnd:Desktop&lt;br /&gt;&lt;br /&gt;Option 1 above doesn't give us as much of a boost as I was hoping. Another Mac developer here would really like to see option 2 implemented. Here is the theory behind the possible speedup from option 2.&lt;br /&gt;&lt;br /&gt;A large part of the time we spend in file operations is converting a LabVIEW path (HFS Classic Style) to a file system representation (FSRef) so we can call the OS APIs. If we instead just convert the path to a string (which is just one step in the HFS method), but a UNIX string, and then call UNIX APIs, the theory is that it will be much faster.&lt;br /&gt;&lt;br /&gt;In order for this to be the most efficient, we would have to change the string format of paths on the Mac so they would be UNIX style instead of HFS Classic style. That means any string constants of paths would break.&lt;br /&gt;&lt;br /&gt;So we are left to puzzle over compatibility vs performance trade-offs.&lt;br /&gt;&lt;br /&gt;If you have concerns or an opinion on this post, please post a comment below.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19928387-114321348100680828?l=themacview.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://themacview.blogspot.com/feeds/114321348100680828/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19928387&amp;postID=114321348100680828' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19928387/posts/default/114321348100680828'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19928387/posts/default/114321348100680828'/><link rel='alternate' type='text/html' href='http://themacview.blogspot.com/2006/03/performance-compatibility-links-and.html' title='Performance, Compatibility, Links and Aliases'/><author><name>Marc Page</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-KXZHHLyZcGU/AAAAAAAAAAI/AAAAAAAAJuU/PGlqPNBP9l4/s512-c/photo.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-19928387.post-113883000032902831</id><published>2006-03-03T13:39:00.000-08:00</published><updated>2006-03-03T10:26:02.680-08:00</updated><title type='text'>How to Create a Reference to Data</title><content type='html'>LabVIEW is, by design, a by-value language. You can modify the data on one wire, and as long as you fork that wire before the modification, the data on the other side of the fork will not be modified. There are a few places where this is not the case, but in general, that is how things work.&lt;br /&gt;&lt;br /&gt;There are times when you would want a reference to the data instead of passing the data directly on the wires. One reason would be to be able to reference a change in data on a completely different VI (or block of a VI). This can be done now with globals or VI server references to controls.&lt;br /&gt;&lt;br /&gt;Another reason to have references to data is to cut down on the possibilities of copies being made of the data. I've had LabVIEW run out of memory when I had a hash table (array of cluster of 2 strings) with some large strings in them, and a lot of them. This data type was being passed everywhere, and would eventually eat up all of the memory. It didn't have to, it wasn't that big, but it was just copied everywhere. All this copying also can effect performance.&lt;br /&gt;&lt;br /&gt;You can use a global or even a VI server reference to a control, but then you have to know how many different sets of data you are going to have. There has to be a global or a control for each different set of data. It is also not very safe if you have a large data type. For instance, with my hash table if I where to get the value out of the global, modify it and put it back into the global, someone could have replaced the data in the global before I had a chance to put the data back, and I would overwrite the other change.&lt;br /&gt;&lt;br /&gt;How do you overcome these issues? Queues (Functions Palette -&gt; Data Communication -&gt; Queue Operations). To create a new reference to data, drop an Obtain Queue primitive. This would be like the new operator in C++ or Java. It allocates space for your data. The only input you need to wire is the data type (and error in if you have one). Now this only allocates the space, it does not fill it in.&lt;br /&gt;&lt;br /&gt;To set the value pointed to by your reference, drop the Enqueue Element primitive. Wire up the Queue reference wire, the error wire and then wire your data to put into the "Reference." The Queue Out terminal will now contain a Reference to your data.&lt;br /&gt;&lt;br /&gt;There are a couple of important things to remember about this "Reference."&lt;br /&gt;&lt;br /&gt;1. If you fork the wire, the data will not be copied. As long as the data stays in the Reference (queue), it will never be copied.&lt;br /&gt;&lt;br /&gt;2. There is only one copy of the data. If you fork the wire and modify the contents of the queue, you have modified the value on the other side of the fork as well.&lt;br /&gt;&lt;br /&gt;To modify the value pointed to by the Reference (queue), you need to Dequeue the data and then Re-Enqueue it. You will also do this to read the value. First, drop the Dequeue Element primitive and wire up the Queue and Error In terminals. Take the Element output and fork it out, modify it, whatever you want to do with the value in the Reference (queue). Then when you are done, drop the Enqueue Element primitive and re-Enqueue the data (original if you are reading, or modified value if you are modifying the value).&lt;br /&gt;&lt;br /&gt;Dequeue and Enqueue give us a protection mechanism known as thread-safety. It prevents two people from reading the data, and then writing data over the results of one another. This is important in a data-flow language like LabVIEW, in which "threading" is transparently accomplished in the language itself.&lt;br /&gt;&lt;br /&gt;Dequeue and Enqueue also do not copy the data, but rather move the data out of the queue. This is an important speed issues when you have large data structures.&lt;br /&gt;&lt;br /&gt;Then when you are completely done with the Reference (queue), you use the Release Queue primitive. This will release any memory used to store the data and will cause all future uses of the Reference (queue) to return errors. This is the equivalent to delete in C++ (Java has no equivalent).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19928387-113883000032902831?l=themacview.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://themacview.blogspot.com/feeds/113883000032902831/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19928387&amp;postID=113883000032902831' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19928387/posts/default/113883000032902831'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19928387/posts/default/113883000032902831'/><link rel='alternate' type='text/html' href='http://themacview.blogspot.com/2006/03/how-to-create-reference-to-data.html' title='How to Create a Reference to Data'/><author><name>Marc Page</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-KXZHHLyZcGU/AAAAAAAAAAI/AAAAAAAAJuU/PGlqPNBP9l4/s512-c/photo.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-19928387.post-113501982727226406</id><published>2006-02-24T10:54:00.000-08:00</published><updated>2006-02-23T08:27:17.313-08:00</updated><title type='text'>Using Libraries (not LLBs) To Group Your VIs</title><content type='html'>In previous posts, I looked at how to wrap OS calls in LabVIEW. Now I will look at packaging them up. While I will be referring to how to package up the calls into the OS, it is also a general topic.&lt;br /&gt;&lt;br /&gt;The easiest way to create a library is to first create a project (File -&gt; New Project). Control-Click (Right-Click) on My Computer and select New -&gt; Library. Now select File -&gt; Save All, and save the project and library to disk (create a new folder in the file dialog).&lt;br /&gt;&lt;br /&gt;The next question is "What do I name my library?" I would suggest using your reverse DNS name. For instance, If I was making a library for Carbon, I may use "com.Apple.Carbon" as the name. Now preferrably Apple would make this, but if you don't think they would, you can use their name. In the higher level code that uses the Carbon APIs, I may name that library "com.ni.Carbon".  &lt;br /&gt;&lt;br /&gt;Now inside of Libraries, you can have a library. For instance, say you wanted to have a CoreFoundation library inside of Carbon. So you would control-click (right-click) on com.Apple.Carbon, and select New -&gt; Library. Then save that library as CoreFoundation (or CF). You may want to make a new directory in the com.Apple.Carbon directory to save the library. And then within the CoreFoundation library, you could have a String library (for CFStringRef functions).&lt;br /&gt;&lt;br /&gt;What creating levels of libraries like this does is enable you to have VIs named the same (in different libraries) and still be able to work in LabVIEW together. For instance, say you had a VI called GetTypeID that wrapped CFStringGetTypeID (&lt;a href="http://developer.apple.com/documentation/CoreFoundation/Reference/CFStringRef/Reference/reference.html#//apple_ref/doc/uid/20001211-CH201-F11151"&gt;&lt;/a&gt;). The full name of that VI would be com.Apple.Carbon:CoreFoundation:String:GetTypeID, so it could peacefully coexist with com.Apple.Carbon:CoreFoundation:Array:GetTypeID. You could have them both on the same diagram and there would be no problems.&lt;br /&gt;&lt;br /&gt;I would suggest having a namespace for each library you call into. That library would then be just thin wrappers around the calls to the entry points in the library (like com.Apple.Carbon). Then have a separate library that are convert the calls into more useful LabVIEW calls (like com.NI.Carbon). Inside each library, add a library for each group of calls (in Carbon it would be a library for each manager). If the manager is divided into different objects it works with, then create another library level for each of the different objects. If you use any clusters, save them as typedefs in that library. If you have helper functions you can make them private in that library (or public if their usefulness extends beyond the library).&lt;br /&gt;&lt;br /&gt;Anyway, just some basic ideas on how to make a well packaged wrapper around a Shared Library.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19928387-113501982727226406?l=themacview.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://themacview.blogspot.com/feeds/113501982727226406/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19928387&amp;postID=113501982727226406' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19928387/posts/default/113501982727226406'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19928387/posts/default/113501982727226406'/><link rel='alternate' type='text/html' href='http://themacview.blogspot.com/2006/02/using-libraries-not-llbs-to-group-your.html' title='Using Libraries (not LLBs) To Group Your VIs'/><author><name>Marc Page</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-KXZHHLyZcGU/AAAAAAAAAAI/AAAAAAAAJuU/PGlqPNBP9l4/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-19928387.post-114073667112812958</id><published>2006-02-23T15:15:00.000-08:00</published><updated>2006-03-03T10:25:13.323-08:00</updated><title type='text'>Change in Posting Frequency</title><content type='html'>I have not been happy with the quality of my posts up to this point. They have been heavy on details, and sometimes difficult to follow. I would like to spend more time developing each entry, and adding images to make the material more clear. &lt;br /&gt;&lt;br /&gt;To this end, I will now be updating once a month instead of once a week. This will give me the time to flush out the topics better and generate the images to better explain the ideas.&lt;br /&gt;&lt;br /&gt;I appreciate all the comments and support so far, and I will be actively responding to comments on postings.&lt;br /&gt;&lt;br /&gt;Have a Mac day!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19928387-114073667112812958?l=themacview.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://themacview.blogspot.com/feeds/114073667112812958/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19928387&amp;postID=114073667112812958' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19928387/posts/default/114073667112812958'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19928387/posts/default/114073667112812958'/><link rel='alternate' type='text/html' href='http://themacview.blogspot.com/2006/02/change-in-posting-frequency.html' title='Change in Posting Frequency'/><author><name>Marc Page</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-KXZHHLyZcGU/AAAAAAAAAAI/AAAAAAAAJuU/PGlqPNBP9l4/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-19928387.post-113501539283899774</id><published>2006-02-17T10:02:00.000-08:00</published><updated>2006-02-16T06:36:38.850-08:00</updated><title type='text'>ADVANCED: How To Call The Mac OS Directly From LabVIEW Part VII: Putting It All Together</title><content type='html'>See Part I of this series for the obligatory warning about using the Call Library Function Node.&lt;br /&gt;&lt;br /&gt;Now let's take a look at some advanced techniques for handling some very complicated structures in calls. Take a look at vi.lib/Platform/FileManager.llb/PBGetCatInfo.vi. Discussing how PBGetCatInfoSync (&lt;a href="http://developer.apple.com/documentation/Carbon/Reference/File_Manager/Reference/reference.html#//apple_ref/doc/uid/TP30000107-CH1g-F04767"&gt;Apple's Documentation&lt;/a&gt;) is far beyond the scope of this post. Let's just say that it is a kitchen-sink-included type function. We'll just look at some of the techniques used to make this call more manageable.&lt;br /&gt;&lt;br /&gt;First off, because of the complexity of the structure (a union that contains two structs and each contain structs, arrays pointers, etc.) I decided to just treat the whole block as an array of bytes. We create the aray of bytes of the correct size with the Initialize Array primitive (Programming -&gt; Array). There are a few parameters that need to be set up first: ioName (PStrPtr to a 32 character buffer), ioFDirIndex (I16), ioVRefNum (I16) and ioDirID/ioDrDirID (I32). Since these are inputs, we need to set those spots in the struct to the input data. So we convert them to byte arrays (U8[]) and then replace the Replace Array Subset (Programming -&gt; Array) to set them. This is where finding the offsets of each element of a struct come in handy. Notice that for ioName, we call NewPtr and BlockMove to create a buffer and fill it in with whatever input they gave us. Then we convert that pointer into an array of bytes and put it into the buffer.&lt;br /&gt;&lt;br /&gt;We then make the call to PBGetCatInfoSync. We do the traditional error handling with the return value. We take the array returned and pull out the pointer so we can call DisposePtr.&lt;br /&gt;&lt;br /&gt;Now comes the fun part, getting all the data out. Since this structure has so many values to get out, I found it easier to group them by the data type and loop over an array of indexes (here again its helpful to pre-calculate the offset of each struct member) and do the conversion to that type. So you can see that we have OSType, 8-bit, 16-bit and 32-bit values we pull out. We also pull the string out of the PStr we allocated (before we disposed of it) and create an FSSpec from the parameters and the string.&lt;br /&gt;&lt;br /&gt;Since it is a union, the data at certain offsets can be interpreted in different ways. So we return two different clusters, one for File and one for Directory (and a boolean saying which to look at). We grab the values for each and populate the output.&lt;br /&gt;&lt;br /&gt;While at first glance this seems like a very complicated VI, it is actually not all that bad, there is just a lot of data to look at.&lt;br /&gt;&lt;br /&gt;Well, that's it. With all of this, you can call the OS (specifically Carbon) and do all sorts of wonderful things.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19928387-113501539283899774?l=themacview.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://themacview.blogspot.com/feeds/113501539283899774/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19928387&amp;postID=113501539283899774' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19928387/posts/default/113501539283899774'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19928387/posts/default/113501539283899774'/><link rel='alternate' type='text/html' href='http://themacview.blogspot.com/2006/02/advanced-how-to-call-mac-os-directly_17.html' title='ADVANCED: How To Call The Mac OS Directly From LabVIEW Part VII: Putting It All Together'/><author><name>Marc Page</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-KXZHHLyZcGU/AAAAAAAAAAI/AAAAAAAAJuU/PGlqPNBP9l4/s512-c/photo.jpg'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-19928387.post-113501346283748046</id><published>2006-02-10T09:30:00.000-08:00</published><updated>2006-02-09T06:37:39.360-08:00</updated><title type='text'>ADVANCED: How To Call The Mac OS Directly From LabVIEW Part VI: Documentation and Error Handling</title><content type='html'>Let's take a break from the detailed "how to" of calling the OS, and spend some time talking about documentation and error handling.&lt;br /&gt;&lt;br /&gt;First, lets talk about documentation. Because there is not always a one to one relationship between C code and LabVIEW code, its usually a good idea to include the information from the header file, and any accompanying documentation, on the call. This would include prototype, description, parameter descriptions, return value, side effects, conditions and any other documentation. You will also want to include struct, enum and constant declarations. When including struct documentation, calculate the offsets of each member of the struct and include them in the documentation.&lt;br /&gt;&lt;br /&gt;I like to keep most of this information in labels on the block diagram. That way I can better see a relationship between the C code and the LabVIEW code. If you use any constants, set the label on the constant to the C name for the constant.&lt;br /&gt;&lt;br /&gt;Any of the parameters that you expose on the front panel should have the parameter description and any other documentation from the function description that would be needed to make the call. You will probably also want to include much of the overview and description in the VI documentation also, so it can be read from Context Help.&lt;br /&gt;&lt;br /&gt;As far as error handling, there are a few things to keep in mind. In most cases, if an error comes in, you do not want to make any calls into the OS. The exceptions would be disposeXXX, deleteXXX, freeXXX, releaseXXX, closeXXX, etc. Things that terminate a data type need to be called to do cleanup, and then you have to merge any errors you get with the error in cluster (which gets precedence).&lt;br /&gt;&lt;br /&gt;Usually, there will be a big switch on the error in terminal, with the no error case making the calls. If the call returns an OSErr or an OSStatus, you can check for zero. If it is zero, just return the error in, otherwise, set status to true, the code to the OSErr or OSStatus, and put the VI name in the source (or something meaningful to track down the error).&lt;br /&gt;&lt;br /&gt;If you allocate, retain, create, etc. something on your block diagram, try to make sure it is always cleaned up properly before your diagram ends.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19928387-113501346283748046?l=themacview.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://themacview.blogspot.com/feeds/113501346283748046/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19928387&amp;postID=113501346283748046' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19928387/posts/default/113501346283748046'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19928387/posts/default/113501346283748046'/><link rel='alternate' type='text/html' href='http://themacview.blogspot.com/2006/02/advanced-how-to-call-mac-os-directly_10.html' title='ADVANCED: How To Call The Mac OS Directly From LabVIEW Part VI: Documentation and Error Handling'/><author><name>Marc Page</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-KXZHHLyZcGU/AAAAAAAAAAI/AAAAAAAAJuU/PGlqPNBP9l4/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-19928387.post-113476998652413588</id><published>2006-02-03T13:52:00.000-08:00</published><updated>2006-02-23T08:26:17.300-08:00</updated><title type='text'>ADVANCED: How To Call The Mac OS Directly From LabVIEW Part V: Constant Length Arrays in Structs</title><content type='html'>See Part I of this series for the obligatory warning about using the Call Library Function Node.&lt;br /&gt;&lt;br /&gt;We've looked at several methods of handling different data types when calling into OS calls. Now we're going to look into how to handle constant length arrays in structs (clusters). In LabVIEW, an array in a cluster is really a Handle to an array (32 bit length prefixed), so we cannot just put a LabVIEW array of the type into the struct. There are two methods to handle this. The first is to put the values into the cluster, one by one. If the array is small, or the data does not need to be accessed by the user, this might be usefull (see vi.lib/Platform/FileManager.llb/FSRef.ctl).&lt;br /&gt;&lt;br /&gt;If, however, you need to access the data and the data is non-trivial size (like a PStr32), this can just make code handling a nightmare. FSSpec (&lt;a href="http://developer.apple.com/documentation/Carbon/Reference/File_Manager/Reference/reference.html#//apple_ref/doc/c_ref/FSSpec"&gt;Apple's Documentation&lt;/a&gt;) is one such structure. This is where the second method comes in.&lt;br /&gt;&lt;br /&gt;There are two functions that will flatten an FSSpec-like cluster into an array of bytes, and another to inflate it from an array of bytes. This way we have a very LabVIEW like type that looks a lot like the C data type, and we can convert it into something that can be passed to a call that takes an FSSpecPtr. (in vi.lib/Platform/FileManager.llb, FSSpecToRawData.vi and FSSpecFromRawData.vi).&lt;br /&gt;&lt;br /&gt;&lt;a href="http://photos1.blogger.com/blogger/4215/1982/1600/FSSpecToRawData.png"&gt;&lt;img style="margin:0 10px 10px 0;cursor:pointer; cursor:hand;" src="http://photos1.blogger.com/blogger/4215/1982/400/FSSpecToRawData.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;a href="http://photos1.blogger.com/blogger/4215/1982/1600/FSSpecFromRawData.png"&gt;&lt;img style="margin:0 0 10px 10px;cursor:pointer; cursor:hand;" src="http://photos1.blogger.com/blogger/4215/1982/400/FSSpecFromRawData.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The basics of these are that a PStr32 is a constant size, length prefixed string (array) in the FSSpec struct. We take each element and typecast it into/out of the array.&lt;br /&gt;&lt;br /&gt;For instance, in FSSpecFromRawData.vi, we have a cluster constant that represents the first two items in the struct, and we get the first 6 bytes from the array and typecast it to that cluster and then map that into the output. Then we take the rest of the bytes in the input byte array, get the first byte and use that to determine how many following bytes to use. We then us the Byte Array To String primitive (Programming -&gt; String -&gt; Conversion) to get the string. We put it all together into the output cluster, and we're done.&lt;br /&gt;&lt;br /&gt;So with what has been covered so far, you can handle most of Apple's API calls. The one thing I have found that you cannot handle, without writing C code in a Framework or Bundle, is passing a callback function to something.&lt;br /&gt;&lt;br /&gt;Next we'll look at documenting your VIs that call into the OS.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19928387-113476998652413588?l=themacview.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://themacview.blogspot.com/feeds/113476998652413588/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19928387&amp;postID=113476998652413588' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19928387/posts/default/113476998652413588'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19928387/posts/default/113476998652413588'/><link rel='alternate' type='text/html' href='http://themacview.blogspot.com/2006/02/advanced-how-to-call-mac-os-directly.html' title='ADVANCED: How To Call The Mac OS Directly From LabVIEW Part V: Constant Length Arrays in Structs'/><author><name>Marc Page</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-KXZHHLyZcGU/AAAAAAAAAAI/AAAAAAAAJuU/PGlqPNBP9l4/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-19928387.post-113476882381194657</id><published>2006-01-27T13:33:00.000-08:00</published><updated>2006-01-26T06:21:36.590-08:00</updated><title type='text'>ADVANCED: How To Call The Mac OS Directly From LabVIEW Part IV: Pointers in structs</title><content type='html'>See Part I of this series for the obligatory warning about using the Call Library Function Node. If the warning in Part I gave you reason to pause, this section will really get to you.&lt;br /&gt;&lt;br /&gt;Many times when working with data structures, you will have a pointer to data. Take for instance, GetProcessInformation (&lt;a href="http://developer.apple.com/documentation/Carbon/Reference/Process_Manager/Reference/reference.html#//apple_ref/doc/uid/TP30000208-CH1g-F01980"&gt;Apple's Documentation&lt;/a&gt;). The ProcessInfoRec (&lt;a href="http://developer.apple.com/documentation/Carbon/Reference/Process_Manager/Reference/reference.html#//apple_ref/doc/c_ref/ProcessInfoRec"&gt;Apple's Documentation&lt;/a&gt;) contains a StringPtr (processName) and an FSSpecPtr (processAppSpec). LabVIEW does not allow you to get a pointer to put into these structures, so how do you handle this situation?&lt;br /&gt;&lt;br /&gt;(You can see this example already coded up at vi.lib/Platform/ProcessManager.llb/GetProcessInformation.vi)&lt;br /&gt;&lt;br /&gt;First, we create a cluster to represent the ProcessInfoRec. The order in which the elements are added to the cluster is important. To ensure that the ordering is what you think it is, right click on the cluster and select AutoSizing -&gt; Arrange Vertically. Add the following to an empty cluster (in this order and set their labels as shown below:&lt;br /&gt;&lt;br /&gt;U32 processInfoLength&lt;br /&gt;U32 processName [note really a pointer]&lt;br /&gt;U32 processSerialNumberHigh&lt;br /&gt;U32 processSerialNumberLow&lt;br /&gt;U32 processType&lt;br /&gt;U32 processSignature&lt;br /&gt;U32 processMode&lt;br /&gt;U32 processLocation&lt;br /&gt;U32 processSize&lt;br /&gt;U32 processFreeMem&lt;br /&gt;U32 processLauncherHigh&lt;br /&gt;U32 processLauncherLow&lt;br /&gt;U32 processLaunchDate&lt;br /&gt;U32 processActiveTime&lt;br /&gt;U32 processAppSpec&lt;br /&gt;&lt;br /&gt;Take the constant cluster you just created, and use the Type Cast primitive (Programming -&gt; Numeric -&gt; Data Manipulation) to typecast the cluster to an array of bytes (U8[]). Set the processInfoLength field to the Array Size (Programming -&gt; Array) of the cluster as an array using the Bundle By Name primitive (Programming -&gt; Clusters &amp; Variant) with the cluster constant we created as the input cluster.&lt;br /&gt;&lt;br /&gt;Next we need to to allocate a buffer to hold the processName. We create a Call Library Function Node (Connectivity -&gt; Libraries &amp; Executables) to call into Carbon.* with the function NewPtr (&lt;a href="http://developer.apple.com/documentation/Carbon/Reference/Memory_Manager/Reference/reference.html#//apple_ref/doc/uid/TP30000202-CH1g-F04241"&gt;Apple's Documentation&lt;/a&gt;). Wire a 256 constant to the byteCount input. Take the output from NewPtr Call Library Function Node as a U32 and wire it into the cluster we just set the processInfoLength on (you can grow the Bundle By Name primitive to accommodate more items).&lt;br /&gt;&lt;br /&gt;We can set up a cluster and do similar handling to allocate space for a File Specification, but to simplify, we will just pass NULL (or zero (0)) to let the call know we are not interested in the location. We'll cover FSSpec handling in a future article.&lt;br /&gt;&lt;br /&gt;Create a cluster of two U32s for the ProcessSerialNumber to get information on, and pass it to the first input of the Call Library Function Node for GetProcessInformation. The second input terminal we will wire our initialized cluster into.&lt;br /&gt;&lt;br /&gt;Now the cluster coming out has all the information in it. The fun now is to interpret all the information.&lt;br /&gt;&lt;br /&gt;Let's start with the easy ones. processType and processSignature are OSTypes. You can take the U32s and use the Type Cast primitive to typecast them directly to strings.&lt;br /&gt;&lt;br /&gt;The real easy ones are the numbers that are just numbers.&lt;br /&gt;&lt;br /&gt;Then we come to processName. How do we get information out of a pointer? We use the wonderful BlockMove funtion (&lt;a href="http://developer.apple.com/documentation/Carbon/Reference/Memory_Manager/Reference/reference.html#//apple_ref/doc/uid/TP30000202-CH1g-F00397"&gt;Apple's Documentation&lt;/a&gt;) and GetPtrSize (&lt;a href="http://developer.apple.com/documentation/Carbon/Reference/Memory_Manager/Reference/reference.html#//apple_ref/doc/uid/TP30000202-CH1g-F01985"&gt;Apple's Documentation&lt;/a&gt;), both in the Carbon.* library.&lt;br /&gt;&lt;br /&gt;Since we used NewPtr to allocate the buffer, we can use GetPtrSize to get the size of it (we could just hard code in the size of the data to get out of the pointer).&lt;br /&gt;&lt;br /&gt;We set srcPtr in the BlockMove Call Library Function Node paramter to be the U32 from our cluster (the address of the data). &lt;br /&gt;&lt;br /&gt;For destPtr, we allocate an array of bytes large enough to hold the data, and wire it in as an array. We now have the array of data out of the pointer. Since it is a PStr, we get the first byte and use it as the string length. We then get that many bytes following the length byte and call the Byte Array To String primitive (Programming -&gt; String -&gt; Conversion) to convert them to a string.&lt;br /&gt;&lt;br /&gt;The byteCount can be set to the size of the array passed to destPtr.&lt;br /&gt;&lt;br /&gt;Now that we have the data from the pointer, we should call DisposePtr (&lt;a href="http://developer.apple.com/documentation/Carbon/Reference/Memory_Manager/Reference/reference.html#//apple_ref/doc/uid/TP30000202-CH1g-F01164"&gt;Apple's Documentation&lt;/a&gt;).&lt;br /&gt;&lt;br /&gt;The last part to handle is the error code. If it is a zero, it is no error, just return a no error cluster. If it is non-zero, set the error code in the error cluster and return it.&lt;br /&gt;&lt;br /&gt;And that is it. You can now handle arbitrary structures with pointers to other structures/data. Now because this is a lot of pointer management, there is a chance for buffer overflow, overwriting memory, memory leaks and other nasty problems. You will likely crash LabVIEW when running VIs developed like this, so save often. you may want to learn how to use gdb to attach to LabVIEW to see how, where and why you crashed.&lt;br /&gt;&lt;br /&gt;Next we will look at how to handle constant length arrays in clusters.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19928387-113476882381194657?l=themacview.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://themacview.blogspot.com/feeds/113476882381194657/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19928387&amp;postID=113476882381194657' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19928387/posts/default/113476882381194657'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19928387/posts/default/113476882381194657'/><link rel='alternate' type='text/html' href='http://themacview.blogspot.com/2006/01/advanced-how-to-call-mac-os-directly_27.html' title='ADVANCED: How To Call The Mac OS Directly From LabVIEW Part IV: Pointers in structs'/><author><name>Marc Page</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-KXZHHLyZcGU/AAAAAAAAAAI/AAAAAAAAJuU/PGlqPNBP9l4/s512-c/photo.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-19928387.post-113476880765303537</id><published>2006-01-20T13:33:00.000-08:00</published><updated>2006-01-19T06:38:19.106-08:00</updated><title type='text'>ADVANCED: How To Call The Mac OS Directly From LabVIEW Part III: Simple Parameter Types</title><content type='html'>See Part I of this series for the obligatory warning about using the Call Library Function Node.&lt;br /&gt;&lt;br /&gt;Let's look at another example that shipped with LabVIEW 8.0. In vi.lib/Platform/Miscellaneous.llb, there is a VI, Check Connection To DNS Address.vi. This VI wraps a call to &lt;a href="http://developer.apple.com/documentation/Networking/Reference/SysConfig/SCNetwork/CompositePage.html#//apple_ref/c/func/SCNetworkCheckReachabilityByName"&gt; SCNetworkCheckReachabilityByName &lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;As you can see, the parameters for this call are a little more complicated. First, double click on the Call Library Function Node to see how it is configured. You can see that we are calling into SystemConfiguration.framework (as the documentation above states).&lt;br /&gt;&lt;br /&gt;Notice the Parameter return value is Boolean. This string is the label of the return terminal on the Node. I used Boolean here so that the return value type would be more apparent. However, I did make a mistake. If you look in &lt;a href="file:///System/Library/Frameworks/CoreServices.framework/Frameworks/CarbonCore.framework/Headers/MacTypes.h"&gt;MacTypes.h&lt;/a&gt;, you'll notice that a Boolean is defined to be an unsigned char (or Unsigned 8-bit integer), however, I had the return type declared as an Unsigned 32-bit Integer. Luckily it just happens to work in this case, but it will be changed in a future release.&lt;br /&gt;&lt;br /&gt;To look at the other parameters you can click on the pop-up next to Parameter. You should see three items in the list (the return type and the two parameters). Go ahead and select DNSName. Notice it is a C String Pointer. When you look at Apple's Documentation, it has a const char *nodename parameter, which is a C String Pointer.&lt;br /&gt;&lt;br /&gt;Now lets look at the flags parameter. Notice it is a Pointer to Value. If you look at Apple's Documentation, it says that last parameter is a SCNetworkConnectionFlags, but doesn't say what a SCNetworkConnectionFlags is. If you look in the header file (&lt;a href="file://System/Library/Frameworks/SystemConfiguration.framework/Headers/SCNetwork.h"&gt;SCNetwork.h&lt;/a&gt;), you can see that it is defined to be a uint32_t (Unsigned 32-bit Integer), and it is passed by pointer.&lt;br /&gt;&lt;br /&gt;Now if you look at the dialog (cancel the configuration dialog), you can see that we can just wire a String into the first parameter. The second parameter is an out only parameter, and it is suggested you wire an invalid/NULL/zero value to out inputs.&lt;br /&gt;&lt;br /&gt;We use similar techniques to the ones used in the previous post to get the bits out to return. Note that the Index Array primitive (Programming -&gt; Array) starts at zero be default and increments by one. The last two bits we get out are 16 and 17, so we skip to 16 and the next one would be 17.&lt;br /&gt;&lt;br /&gt;In part IV, we will look at complex data types passed into and out of the Call Library Function Node.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19928387-113476880765303537?l=themacview.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://themacview.blogspot.com/feeds/113476880765303537/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19928387&amp;postID=113476880765303537' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19928387/posts/default/113476880765303537'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19928387/posts/default/113476880765303537'/><link rel='alternate' type='text/html' href='http://themacview.blogspot.com/2006/01/advanced-how-to-call-mac-os-directly_20.html' title='ADVANCED: How To Call The Mac OS Directly From LabVIEW Part III: Simple Parameter Types'/><author><name>Marc Page</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-KXZHHLyZcGU/AAAAAAAAAAI/AAAAAAAAJuU/PGlqPNBP9l4/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-19928387.post-113476878674037354</id><published>2006-01-13T13:29:00.000-08:00</published><updated>2006-01-12T06:19:42.143-08:00</updated><title type='text'>ADVANCED: How To Call The Mac OS Directly From LabVIEW Part II: Converting Data for Ease of Use</title><content type='html'>See Part I of this series for the obligatory warning about using the Call Library Function Node.&lt;br /&gt;&lt;br /&gt;Let's look at some examples that shipped with LabVIEW 8.0. In vi.lib/Platform, there is a VI, Mac Key Modifiers Down.vi. This VI wraps a call to &lt;a href="http://developer.apple.com/documentation/Carbon/Conceptual/Carbon_Event_Manager/Tasks/chapter_3_section_7.html#//apple_ref/doc/uid/TP30000989-CH203-TPXREF112"&gt;GetCurrentEventKeyModifiers&lt;/a&gt;. Like TickCount in Part I, this function just returns a UInt32,&lt;br /&gt;&lt;br /&gt;We could, just like in TickCount, return the UInt32. There are two reasons, in this case, not to. We're writing LabVIEW code and we are writing Mac code. Both reasons encourage us to make the interface more elegant. If you look at &lt;a href="http://developer.apple.com/documentation/Carbon/Conceptual/Carbon_Event_Manager/Tasks/chapter_3_section_10.html#//apple_ref/doc/uid/TP30000989-CH203-CIHGCJAD"&gt;Table 2-1&lt;/a&gt;, you can see the C defined constants, but that doesn't help us much in LabVIEW. So if you look at &lt;a href="file:///System/Library/Frameworks/Carbon.framework/Frameworks/HIToolbox.framework/Headers/Events.h"&gt;Events.h&lt;/a&gt; you can see the rest of the constants. You can see that the keyboard bits don't start until bit 8 (cmdKey[Bit]).&lt;br /&gt;&lt;br /&gt;So we take the output from the Call Library Function Node, and connect it to Number To Boolean Array primitive (Programming -&gt; Boolean). Then we use an Index Array primitive (Programming -&gt; Array), and grow it. We set the first index to 8 (bit 8) and the rest will be sequentially bit 9, 10, etc. We can then create a cluster indicator on the front panel that has all the boolean values we need.&lt;br /&gt;&lt;br /&gt;The version of this VI that shipped with LabVIEW 8.0 used a cluster constant to wire into the Bundle by Name primitive (Programming -&gt; Cluster &amp; Variant). I have since decided on a better way. You can control-click (right-click) on the newly created indicator terminal and select Create -&gt; Local Variable. Then control-click (right-click) on the new local variable and select Change To Read. Then wire the output from the local variable into the Bundle by Name primitive's input cluster. This way if you change the indicator, you do not need to change the constant, it makes the code more robust.&lt;br /&gt;&lt;br /&gt;And there you have it,  we have made a more usable interface for the data returned from a call to the OS. In part III, we will go more in-depth on data types passed into and out of the Call Library Function Node.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19928387-113476878674037354?l=themacview.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://themacview.blogspot.com/feeds/113476878674037354/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19928387&amp;postID=113476878674037354' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19928387/posts/default/113476878674037354'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19928387/posts/default/113476878674037354'/><link rel='alternate' type='text/html' href='http://themacview.blogspot.com/2006/01/advanced-how-to-call-mac-os-directly_13.html' title='ADVANCED: How To Call The Mac OS Directly From LabVIEW Part II: Converting Data for Ease of Use'/><author><name>Marc Page</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-KXZHHLyZcGU/AAAAAAAAAAI/AAAAAAAAJuU/PGlqPNBP9l4/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-19928387.post-113476767316278438</id><published>2006-01-06T13:10:00.000-08:00</published><updated>2006-01-03T14:35:47.020-08:00</updated><title type='text'>ADVANCED: How To Call The Mac OS Directly From LabVIEW Part I: Call Library Function Node Basics</title><content type='html'>This is not for the faint of heart. Using the Call Library Function Node you can easily crash LabVIEW, corrupt memory and do some really bad things to LabVIEW.&lt;br /&gt;&lt;br /&gt;While adding support for several features in LabVIEW on the Mac, we found it fairly easy to call the OS directly from LabVIEW. For some examples of the fruits of this, you can look at many of the VIs in vi.lib/Platform. This will require extensive use of the Call Library Function Node (Connectivity -&gt; Libraries &amp; Executables). It also requires quite a bit of knowledge about the C programming language and &lt;a href="http://developer.apple.com/referencelibrary/API_Fundamentals/Carbon-api-date.html "&gt;Apple's Documentation&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;The first thing to become familiar with is how to use the Call Library Function Node. Once dropped on the block diagram, you double click on it to configure it to be the OS call you want. Most of the calls into the OS will be into Carbon.framework, so in the Library Name or Path, enter "Carbon.*" (without the quotes). The star (*) means framework on the Mac, DLL on Windows and so on Linux. The Carbon framework is not on any other OS, so I could just use .framework, but its less typing to just put a star (*).&lt;br /&gt;&lt;br /&gt;The next step is to set the Function Name. For this example, we will use :TickCount" (again, without the quotes). If you look at &lt;a href="http://developer.apple.com/documentation/Carbon/Reference/Memory_Manag_nt_Utilities/Reference/reference.html#//apple_ref/doc/uid/TP30000153-CH1g-F07882"&gt;Apple's Documentation on TickCount&lt;/a&gt;, you'll see that it takes no parameters and returns a UInt32. So we set the Type for the return type to be Numeric and set the Data Type to Unsigned 32-bit Integer. It should show the Function Prototype to be "unsigned long TickCount(void);" &lt;br /&gt;&lt;br /&gt;One other thing to note is the Run in UI Thread pop-up in the upper-right corner. Many of Apple's APIs are thread-safe. Those that are thread-safe can be changed to Reentrant. If it is not thread-safe, you must keep it Run in UI Thread. When in doubt, use Run in UI Thread.&lt;br /&gt;&lt;br /&gt;Now that you are done configuring the Call Library Function Node, you can control-click (or right-click) on the U32 output of the Node, and select Create Indicator. Then run the VI and you will get the tick count.&lt;br /&gt;&lt;br /&gt;In Part II, we'll look at more advanced calls and more advanced data types.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19928387-113476767316278438?l=themacview.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://themacview.blogspot.com/feeds/113476767316278438/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19928387&amp;postID=113476767316278438' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19928387/posts/default/113476767316278438'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19928387/posts/default/113476767316278438'/><link rel='alternate' type='text/html' href='http://themacview.blogspot.com/2006/01/advanced-how-to-call-mac-os-directly.html' title='ADVANCED: How To Call The Mac OS Directly From LabVIEW Part I: Call Library Function Node Basics'/><author><name>Marc Page</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-KXZHHLyZcGU/AAAAAAAAAAI/AAAAAAAAJuU/PGlqPNBP9l4/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-19928387.post-113476736931376241</id><published>2005-12-30T12:55:00.000-08:00</published><updated>2005-12-29T10:30:32.310-08:00</updated><title type='text'>Advanced String VIs for Cross Platform Support</title><content type='html'>In vi.lib/AdvancedString there are some very useful VIs when it comes to cross platform development.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Command Line String To Path.vi&lt;br /&gt;&lt;br /&gt;This will convert a path String generated by call to System Exec.vi (Connectivity -&gt; Libraries &amp; Executables) to a LabVIEW path. On non-Mac platforms, it does the same thing as the String To Path primitive. On the Mac, it asks the OS to convert it.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Path To Command Line String.vi&lt;br /&gt;&lt;br /&gt;This will convert a Path to a path String that can be used in generating a command to pass to a call to System Exec.vi (Connectivity -&gt; Libraries &amp; Executables) to a LabVIEW path. On non-Mac platforms, it does the same thing as the Path To String primitive. On the Mac, it asks the OS to convert it.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Relative Path To Platform Independent String.vi&lt;br /&gt;&lt;br /&gt;Takes a relative path (one that does not start with a disk name) and converts it to a URL-like path string (uses forward slashes as separators) on all platforms.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Normalize End Of Line.vi&lt;br /&gt;&lt;br /&gt;Converts all the end of line characters (Mac [\r], UNIX [\n] or DOS [\r\n]) in a string into another line ending type. There are two line ending types that you can convert to that are a little different. The Native line ending type is the line ending character that LabVIEW uses on the platform (for the Mac, its carriage return [\r]). This is equivalent to using the End Of Line Constant (Programming -&gt; String). There is also Native Command Line, which is the same as Native on non-Mac platforms. On the Mac, it is line feed [\n] (UNIX). This way you can generate shell scripts, for example, you could use this to make sure it would be in UNIX format.&lt;br /&gt;&lt;br /&gt;Using this VI can help make your code line-ending-agnostic, which makes it more robust.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19928387-113476736931376241?l=themacview.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://themacview.blogspot.com/feeds/113476736931376241/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19928387&amp;postID=113476736931376241' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19928387/posts/default/113476736931376241'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19928387/posts/default/113476736931376241'/><link rel='alternate' type='text/html' href='http://themacview.blogspot.com/2005/12/advanced-string-vis-for-cross-platform.html' title='Advanced String VIs for Cross Platform Support'/><author><name>Marc Page</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-KXZHHLyZcGU/AAAAAAAAAAI/AAAAAAAAJuU/PGlqPNBP9l4/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-19928387.post-113476617352246570</id><published>2005-12-23T12:26:00.000-08:00</published><updated>2005-12-25T08:06:42.803-08:00</updated><title type='text'>Conditional Disable Structure</title><content type='html'>There is a great new feature in LabVIEW 8.0 for cross platform development: The Conditional Disable Structure.  For those familiar with C, this is a #if. You can implement cross platform support in one VI, and the version for the platform it is on will be used. You can find the conditional disable structure in the functions palette under Programming -&gt; Structures.&lt;br /&gt;&lt;br /&gt;As an example, say you wanted to create a VI that will convert a Path into a String that could be used to build up a command for the System Exec.vi (Connectivity -&gt; Libraries &amp; Executables). You can just use Path To String primitive (Programming -&gt; String -&gt; Conversion) in most cases, but on the Mac, the command line takes UNIX style paths, and Path To String will produce a Classic style path. As it turns out, there is a VI, vi.lib/Platform/CFURL.llb/PathToUNIXPathString.vi, however this VI is only on the Mac.&lt;br /&gt;&lt;br /&gt;If you wanted to make a VI that did the right thing for on every platform, before the Conditional Disable Structure existed, you would have a case structure that used the Property Node (Programming -&gt; Application Control) with Application -&gt; Target -&gt; Operating System property to determine the OS at runtime. In the default case you would just use the Path To String primitive. In the Carbon (Mac OS X is Carbon, don't be fooled by the Mac [Classic] item) case, you would open a reference to PathToUNIXPathString.vi (Programming -&gt; Application Control -&gt; Open VI Reference), call the VI by reference (Programming -&gt; Application Control -&gt; Call by Reference Node) and then close the reference (Programming -&gt; Application Control -&gt; Close Reference). You would have to do this so the VI would not be broken on non-Mac platforms, since PathToUNIXPathString.vi is only there on the Mac.&lt;br /&gt;&lt;br /&gt;There are a few problems with this method. The first is that you have to create a type specifier VI refnum to get the connector pane correct on the Call by Reference Node (passed to Open VI Reference). You also have to get the path to the VI to call correct (which may change if you build it into an Application or Shared Library). It is also a common mistake to forget to close the VI reference, and have a VI reference leak. Basically, the code is difficult to write, difficult to maintain and difficult to get right.&lt;br /&gt;&lt;br /&gt;With the Conditional Disable Structure, you have two cases. The default case will just have the Path To String primitive. The second case will be TARGET_TYPE == Mac. In that case, just drop the PathToUNIXPathString.vi and wire it up. And there you have it.&lt;br /&gt;&lt;br /&gt;Now there is a small annoyance with this method. On the non-Mac platforms, when the VI is loaded and needs to be re-compiled for any reason, it will do a quick search for PathToUNIXPathString.vi, but the VI will come up as runnable.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19928387-113476617352246570?l=themacview.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://themacview.blogspot.com/feeds/113476617352246570/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19928387&amp;postID=113476617352246570' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19928387/posts/default/113476617352246570'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19928387/posts/default/113476617352246570'/><link rel='alternate' type='text/html' href='http://themacview.blogspot.com/2005/12/conditional-disable-structure.html' title='Conditional Disable Structure'/><author><name>Marc Page</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-KXZHHLyZcGU/AAAAAAAAAAI/AAAAAAAAJuU/PGlqPNBP9l4/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-19928387.post-113475599986743047</id><published>2005-12-16T09:35:00.000-08:00</published><updated>2005-12-16T09:59:59.876-08:00</updated><title type='text'>New Mac Features in LabVIEW 8.0</title><content type='html'>With all of the bullet features added to LabVIEW in the latest release, I feel that a lot of the new Mac features were glossed over. Most of them are little ones, but they sure make life easier.&lt;br /&gt;&lt;br /&gt;One cool new feature, that is Mac-only, currently, is the Goto LabVIEW Folder button in Open dialog boxes. If the dialog supports VIs, there will be a Goto LabVIEW Folder in the lower left corner. This is especially helpful if you have several versions of LabVIEW installed (7.0, 7.1, 8.0) and several running at the same time. You'll go right to the directory of the current LabVIEW.&lt;br /&gt;&lt;br /&gt;Another nice feature is the scroll wheel. If you use a Apple's Mighty Mouse, or any scroll wheel mouse, you can scroll the block diagram or front panel. LabVIEW supports horizontal and vertical scroll wheels. You can also emulate the horizontal by holding down the shift key when scrolling.&lt;br /&gt;&lt;br /&gt;Another Mac-only feature is the ability to use Keyboard shortcuts in the "Save Changes?" dialog. Using Command-S will perform the Save (or Save All) operation. Command-D will perform the Don't Save (or Don't Save All or Defer Decision) operation. Escape key should work on all platforms for cancel.&lt;br /&gt;&lt;br /&gt;In vi.lib, we added a couple more fun Mac specific VIs. One VI tells the state of keyboard modifiers (ie Shift, Control, Command, Option). One tells the current state of the mouse buttons. The third will run an arbitrary AppleScript (as a string). These VIs can be found in vi.lib/Platform.&lt;br /&gt;&lt;br /&gt;Many people do not know about the treasure trove of Mac specific things found in vi.lib/Platform. There are several Carbon APIs that are wrapped in VIs. Some are for the more advanced developer who is familiar with Mac APIs, but there are some higher level ones, like CFURL.llb/PathToUNIXPathString.vi and CFURL.llb/UNIXPathSTringToPath.vi. Another useful high level VI is FileSystem.llb/FindFolder to LV Path.vi. You can ask the system to tell you where certain special folders are on the system.&lt;br /&gt;&lt;br /&gt;In the future I will post helpful hints on what you can do with LabVIEW and the Mac.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19928387-113475599986743047?l=themacview.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://themacview.blogspot.com/feeds/113475599986743047/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19928387&amp;postID=113475599986743047' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19928387/posts/default/113475599986743047'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19928387/posts/default/113475599986743047'/><link rel='alternate' type='text/html' href='http://themacview.blogspot.com/2005/12/new-mac-features-in-labview-80.html' title='New Mac Features in LabVIEW 8.0'/><author><name>Marc Page</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-KXZHHLyZcGU/AAAAAAAAAAI/AAAAAAAAJuU/PGlqPNBP9l4/s512-c/photo.jpg'/></author><thr:total>7</thr:total></entry></feed>
