Jump to content

Calculating size of cluster with cast fails, using flatten adds unwanted data


Recommended Posts

Hi,

I need to pass some data to a DLL and need to pass the number of bytes I'm passing also.

I tried using 'cast' (should accept anything) for getting the memmap but this fails (polymorphic input cannot accept this datatype) due to an array inside the cluster.

Then I wanted to switch to 'flatten to string' for getting the same result and now the arraysize is prepended before the arraydata

I stripped down the code to the bare parts but I don't want to unbundle all elements from my original cluster, just for getting the size.

post-2311-0-54392300-1331124341_thumb.pn

Attached you can find a LV8.5 version, the behaviour in LV 2010 SP1 is exactly the same.

cast_fails4.vi

thx

tnt

Link to comment

This is working exactly the way one should expect. If you have a fixed size array that you need to pass (it's always the same size) you can use a cluster instead of an array. LabVIEW will flatten a cluster of simple types into a stream without adding any length element. If your data array may be different sizes on each call then you're doing it the only way I know of.

Mark

Link to comment
This is working exactly the way one should expect.

Can you explain this a bit mo(o)re?

cast_fails.PNG

Is it a LV-bug that the cast does not accept a cluster containing an array?

Is it a LV-bug that the flatten to string adds 4 unwanted bytes for the arraylength while 'prepend..' is set to FALSE?

Edited by tnt
Link to comment

Is it a LV-bug that the cast does not accept a cluster containing an array?

I'm not sure, however using a cast can lead to unforseen results (for instance instant memory issues)

Is it a LV-bug that the flatten to string adds 4 unwanted bytes for the arraylength while 'prepend..' is set to FALSE?

Nope, the 'False' is only for the top level element (cluster), and not for any objec tinside the cluster.

Ton

Link to comment

Can you explain this a bit mo(o)re?

Is it a LV-bug that the cast does not accept a cluster containing an array?

I'm pretty sure it's because you can't type cast any cluster that has a variable length element - if you add a string to a cluster, the type cast won't accept that as a vaild input, either.

From the LabVIEW help on flattened data

"LabVIEW converts data from the format in memory to a form more suitable for writing to or reading from a file. This more suitable format is called flattened data.

Because LabVIEW stores strings, arrays, and paths in handles (pointers to pointers in separate regions of memory), clusters that contain these strings and arrays are noncontiguous."

A basic type cast operation just tries to take a chunk of memory and change the type associated with that chunk. I don't know the internal implementation of the LV type cast, but I'm sure it's more involved and does checks on the validity of the cast. But still, since the memory chunk containing the elements referenced above is not contiguous, you can't just call that memory chunk a new type (like a string) since that chunk doesn't contain all of the data referenced by that type.

Edited by Mark Smith
Link to comment

Is it a LV-bug that the cast does not accept a cluster containing an array?

No.

You cannot cast clusters containing variable length items (like strings and arrays) but the clusters can be contained within an array and can be compund types. If you could set the length of the arrays to be a specific value, then you would be able to use arrays etc within the cluster (as you can with FPGA), but this feature isn't available in normal LabVIEW.

The cluster is synonymous with the C "structure" (struct) which also cannot define variable length arrays within its definition.

  • Like 1
Link to comment

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:

post-11742-0-35007700-1331140130.png

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.

  • Like 1
Link to comment

To divert a little here: are you sure you need to do this? In my experience, when calling DLLs that have a BufferData input array and a sizeofBufferData input numeric, all you need to do is put your byte array into BufferData, and put the number of elements of BufferData into sizeofBufferData (note: your BufferData array in the cluster is an array of I32 - my guess is that they're bytes so they should be U8).

Link to comment

To divert a little here: are you sure you need to do this? In my experience, when calling DLLs that have a BufferData input array and a sizeofBufferData input numeric, all you need to do is put your byte array into BufferData, and put the number of elements of BufferData into sizeofBufferData (note: your BufferData array in the cluster is an array of I32 - my guess is that they're bytes so they should be U8).

I cannot do much about the way the data is expected, I have to pass some kind of header followed by the BufferData and this all packed together as an array of bytes.

The example was just a stripped down version, the BufferData itself is in fact an array of structures containing different types of data.

I was just looking for an easy way to convert the header and the data to U8[]

without having to go manually through all elements (header and buffer) for converting to U8 and pasting it together.

Link to comment

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.