Jump to content
tnt

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

Share this post


Link to post
Share on other sites

You will have to unbundle the elements of the cluster and count the number of bytes of each element.

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites

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).

Share this post


Link to post
Share on other sites

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.

Share this post


Link to post
Share on other sites

Join the conversation

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

Guest
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.


  • Similar Content

    • By Aristos Queue
      Over in the community forum, I have finally gotten around to posting the prototype for my serialization library. The prototype supports serialization to and from JSON for 9 data types and to XML (my own schema) for the same 9 (listed below).
      https://decibel.ni.com/content/docs/DOC-24015
      Please take a look. I've made it a priority to finish out the data type support for the framework generally and for the JSON format specifically. I will need community help to tackle any other formats: the framework is designed to make a single pair of functions on a class handle any file format, but the particular formats on the back end are not my specialty.
      Please post all feedback on the ni.com site so that they stay all in one place and I can follow the threads easier.
×
×
  • Create New...

Important Information

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