It is very important to realize the cast or flatten primitives do not provide you with the binary form of the data as represented in memory. They do provide you with a serial form of the data which can be used to rebuild the data. It's an important distinction.
When passing variable length data into DLLs, break them out of any struct/clusters. Fixed length clusters are fine, so long as you're mindful of byte boundaries/padding (#pragma pack(), etc). For arrays and such, pass in two items, an integer specifying the length, then the actual array as an array data pointer.
For example:
This code calls a DLL to generate 3 arrays of data all of equal size. It first initializes three dummy arrays at a known maximum size, then passes the arrays, along with their size to the DLL, which populates the arrays with data. The DLL knows not to exceed the given size, and returns the actual number of elements used, so LabVIEW then trims the arrays if needed after the DLL call.
The other way of doing it is to make two serial calls to a DLL, one to determine the size of the arrays you'll need, LabVIEW then initializes the arrays, then call the DLL again by supplying the appropriate sized array. Which to use really depends on where your bottleneck is.