ADVANCED: How To Call The Mac OS Directly From LabVIEW Part V: Constant Length Arrays in Structs
See Part I of this series for the obligatory warning about using the Call Library Function Node.
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).
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 (Apple's Documentation) is one such structure. This is where the second method comes in.
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).
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.
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 -> String -> Conversion) to get the string. We put it all together into the output cluster, and we're done.
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.
Next we'll look at documenting your VIs that call into the OS.
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).
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 (Apple's Documentation) is one such structure. This is where the second method comes in.
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).
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.
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 -> String -> Conversion) to get the string. We put it all together into the output cluster, and we're done.
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.
Next we'll look at documenting your VIs that call into the OS.
0 Comments:
Post a Comment
<< Home