DOWNLOAD (Windows Only)

(Windows) Refer to the labview\examples\Connectivity\Libraries and Executables\Libraries and Executables.lvproj for an example of using arrays and strings in shared libraries (DLLs).

Arrays of Numeric Data

Arrays of numeric data can be comprised of any type of integers or floating point numbers with single (4-byte) or double (8-byte) precision. When you pass an array of data to a shared library function, you can pass the data as an array data pointer, as a LabVIEW array handle, or as a LabVIEW array handle pointer.

Array Data Pointers have the following characteristics whether you pass the Array Data Pointers in the Windows API or in another API:

You can set the number of dimensions in the array, but you must not include information about the size of the array dimension(s). Instead, you must pass the size of the array dimension(s) information to your shared library in a separate variable.

Never resize an array or perform operations that might change the length of the array data passed from LabVIEW. Resizing might cause a crash because the pointer sent is not an allocated block but points into the middle of an allocated block.

To return an array of data, you should allocate an array of sufficient size in LabVIEW, pass the array to your function, and have this array act as the buffer. If the data takes less space, you can return the correct size as a separate parameter and then, on the calling diagram, use array subset to extract the valid data.

Remember that the Windows API does not use LabVIEW array handles, so with functions that are part of the Windows API you can use only Array Data Pointers.

String Data

The types of your string pointers must match the types of string pointers that your function uses, or errors occur. The Call Library Function Node offers the following choices:

C String Pointer is a pointer to the string, followed by a NULL character. Most Win32 API functions use this C-style string pointer.

Pascal String Pointer is a pointer to the string, preceded by a length byte.

LabVIEW String Handle is a pointer to a pointer to the string, preceded by four bytes of length information.

LabVIEW String Handle Pointer is a pointer to a handle for a string, preceded by four bytes of length information.

You can think of a string as an array of characters. Assembling the characters in order forms a string. LabVIEW stores a string in a special format in which the first four bytes of the array of characters form a 32-bit signed integer that stores how many characters appear in the string. Thus, a string with n characters requires n + 4 bytes to store in memory. For example, in the following illustration, the string text contains four characters.

When LabVIEW stores the string, the first four bytes contain the value 4 as a 32-bit signed number, and each of the following four bytes contains a character of the string. The advantage of this type of string storage is that NULL characters are allowed in the string. Strings are virtually unlimited in length, up to 231 characters. This method of string storage is shown in the previous illustration. If you pass a LabVIEW string handle from the Call Library Function Node to the shared library, then you can use the LabVIEW Manager functions, such as DSSetHandleSize, to resize the LabVIEW string handle.

The Pascal string format is nearly identical to the LabVIEW string format, but instead of storing the length of the string as a 32-bit signed integer, the string length is stored as an 8-bit unsigned integer. Storing the string length as an 8-bit unsigned integer limits the length of a Pascal-style string to 255 characters. A Pascal string that is n characters long will require n + 1 bytes of memory to store. The following illustrations shows a Pascal string.

C strings are probably the type of strings you will deal with most commonly. The similarities between the C-style string and normal numeric arrays in C becomes much more clear when you see that C strings are declared as char*, where char is typically an 8-bit unsigned integer. Unlike LabVIEW and Pascal strings, C strings do not contain any information that directly gives the length of the string. Instead, C strings use a special character called the NULL character to indicate the end of the string. NULL is defined to have a value of zero in the ASCII character set. Notice that NULL is the number zero and not the character “0.” Thus, in C, a string that contains n characters requires n + 1 bytes of memory to store: n bytes for the characters in the string and one additional byte for the NULL termination character. The following illustration shows how a C-style string is stored in memory.

The advantage of C-style strings is that they are limited in size only by available memory. However, if you are acquiring data from an instrument that returns numeric data as a binary string, as is common with serial or GPIB instruments, values of zero in the string are possible. If you treat the string as a C-style string, your program incorrectly assumes that the end of the string has been reached, when in fact your instrument is returning a numeric value of zero. For binary data that might contain NULL values, consider using an array of 8-bit unsigned integers.

Observe the following guidelines when passing string data to a shared library:

Never resize a string, concatenate a string, or perform operations that might increase the length of string data passed from LabVIEW if you are using the C or Pascal string pointers.

If you must return data as a string, allocate a string of the appropriate length in LabVIEW and pass this string into the shared library to act as a buffer.

You can specify the string size and allocate the correct amount of memory with the Minimum size control on the Parameters tab of the Call Library Function dialog box. If you pass in a string that is smaller than the Minimum size, LabVIEW enlarges the size of the string to the minimum.

Determining When to Resize Array and String Handles in Shared Libraries

When a shared library function increases the size of a string or array that you passed by handle, you need to adjust the size of the handle that references the data. You can adjust the handle size using the memory manager routine DSSetHandleSize. Because this routine requires you to calculate the size of the new memory space, you must account for platform-dependent requirements about how you align and pad memory. A piece of data is aligned if it falls on a boundary equal to a multiple of its size. For example, a 2-byte value is at a memory address that is a multiple of 2 and a 4-byte value is at a memory address that is a multiple of 4. On Intel processors the maximum alignment is 4.

The following examples highlight alignment differences on various platforms for a three-dimensional array of clusters, with each cluster containing a double-precision, floating-point number and a 1-byte Boolean:

(Windows) The first twelve bytes describe the size of each dimension of the array (four bytes per dimension). Cluster elements follow, with each cluster element consisting of an 8-byte double-precision floating-point number followed by a 1-byte Boolean. LabVIEW ignores alignment on Windows.

(64-bit LabVIEW running on Windows) The first twelve bytes describe the size of each dimension of the array (four bytes per dimension) followed by four bytes of padding. Cluster elements follow, with each cluster element consisting of an 8-byte double-precision floating-point number followed by a 1-byte Boolean and seven bytes of padding.

(OS X and Linux) The first twelve bytes describe the size of each dimension of the array (four bytes per dimension). Cluster elements follow, with each cluster element consisting of an 8-byte double-precision floating-point number followed by a 1-byte Boolean and three bytes of padding.

Note Although you must use DSSetHandleSize to resize a string or an array of arbitrary data type, you can use the NumericArrayResize manager routine to resize arrays of numeric data. NumericArrayResize automatically accounts for platform-dependent alignment requirements.

Array and String Tip

When you are not passing LabVIEW handles and your shared library function must create an array, resize an array, or resize a string of data, you should break the shared library function into the following two shared library functions:

Determine the number of elements that the array requires or the length of the string to be returned. Have the first shared library function return the desired size to LabVIEW.

In LabVIEW, initialize an array or string with default values and pass this array to the second shared library function in your shared library, which actually places the data into the array. If you are working with string-based instrument control, it might be easier to pass an array of 8-bit integers than C strings because of the possibility of having NULL values in the string.

When you are passing a LabVIEW array handle or LabVIEW string handle from the Call Library Function Node to your shared library, you can use the LabVIEW Manager functions to resize or create an array or string.

WAS THIS ARTICLE HELPFUL?

Helpful

Not Helpful

Thank you for your feedback.

You changed your response to Helpful

You changed your response to Not Helpful

This site uses cookies to offer you a better browsing experience. Learn more about our privacy policy.