LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Copy untyped void * buffer over LabView struct equivalent

It's been more than a few years since I've used LabView.  Is it possible to overlay a LabView equivalent of a C/C++ struct over an untyped buffer or array?  I wrote a DLL, which seems to work just fine.  One of the parameters it returns is an untyped buffer.  Depending on how its being used, this buffer has a C/C++ struct that defines whats in it.  How can I define a similar struct in labview, and overlay that over the buffer (i.e. StructType *struct = (StructType *) untypedBuffer;)?  I think the LabView equivalent of a struct is a cluster.

0 Kudos
Message 1 of 39
(4,342 Views)

The information itself should be able to be TypeCast to a cluster, but the pointers are usually a hazzle.

/Y

G# - Award winning reference based OOP for LV, for free! - Qestit VIPM GitHub

Qestit Systems
Certified-LabVIEW-Developer
0 Kudos
Message 2 of 39
(4,332 Views)

It depends if the structure contains pointers or not. Any pointer element such as variable sized data elements including strings and arrays, or function pointers will not be possible to be simply mapped to LabVIEW datatypes. If the structure only contains skalars or fixed sized arrays you can define in LabVIEW a cluster with compatible memory layout and pass that cluster directly to the according function parameter.

 

Since LabVIEW is an early binding language you obviously can't switch the cluster type on the fly but instead will to have to write one VI with the correct structure type for each possible pointer type of your function and call them in the correct places.

Rolf Kalbermatter  My Blog
DEMO, Electronic and Mechanical Support department, room 36.LB00.390
0 Kudos
Message 3 of 39
(4,326 Views)

All contents are scalars or fixed sized arrays.  This is basically just a simple network messaging protocol.  The user will define a specific message contents and mapping in the VI, request the current value for that specific message, and the DLL will return an untyped buffer containing that message.  The problem is I can't recompile the DLL everytime a new message is defined or layout is changed.  I wanted to be able to do that in the VI and leave the DLL generic.  When reading a message, the DLL just gets passed an integer ID, and returns the address to the buffer and the size of the buffer.  When writing a message, the DLL jgets passed the same thing.  The DLL neither cares, nor knows what the buffer actually contains.  

 

We're already doing this in c++.  I'm using LabView for development displays and controls, and to provide quick and simple simulation stubs until our simulation environment catches up with the target software.  So the user needs to be able to define the message structure and write any code to pull it out of the untyped buffer, within the VI.  I can easily cast in c++, in fact thats how the target code does this.  How do I cast an address over a cluster in the VI?

 

Yes.  The user will define a cluster for each message mapping.  But I only have one DLL.  Either the DLL can just return an address, and I have to figure out how to cast or copy this to the cluster from within the VI.  Or, the DLL can get passed an address to a cluster, copy it in the DLL.  How can this be done?

0 Kudos
Message 4 of 39
(4,309 Views)

no need to recompile the DLL at all. It seems you think that the type you see in the Call Library Node has to match with what the DLL defines. That is not true at all. All the DLL interface really matters is that the caller (here LabVIEW) and the callee (your function) do agree on the actual data put into the pointer. If the DLL prototype calls this char *, void *, my_superstruct * or whatever doesn't matter.

 

What you tell LabVIEW to put in the cluster has to match with what the DLL wants to pull from the structure, that is all that matters. So you can write xig VIs all implementing various cluster types being passed to that function and all of them calling into the same DLL function. Of course your function will probably need a parameter that tells it what specific datatype the caller has used. It's a possibility that this is not part of the function call itself but depends on some other function called previously but that is rather unsafe to do, and I would not recommend to use that if possible to do otherwise.


@bitblti wrote:

All contents are scalars or fixed sized arrays.  This is basically just a simple network messaging protocol.  The user will define a specific message contents and mapping in the VI, request the current value for that specific message, and the DLL will return an untyped buffer containing that message.  The problem is I can't recompile the DLL everytime a new message is defined or layout is changed.  I wanted to be able to do that in the VI and leave the DLL generic.  When reading a message, the DLL just gets passed an integer ID, and returns the address to the buffer and the size of the buffer.  When writing a message, the DLL jgets passed the same thing.  

 

We're already doing this in c++.  I'm using LabView for development displays and controls, and to provide quick and simple simulation stubs until our simulation environment catches up with the target software.  So the user needs to be able to define the message structure and write any code to pull it out of the untyped buffer, within the VI.  I can easily cast in c++, in fact thats how the target code does this.  How do I cast an address over a cluster in the VI?


 

Rolf Kalbermatter  My Blog
DEMO, Electronic and Mechanical Support department, room 36.LB00.390
0 Kudos
Message 5 of 39
(4,302 Views)

I know what to do and how to do it in code.  I don't know how to do it in LabView.  I know that I can just pass an address and cast a struct to it.  Thats how the code under test does this.  I created a 1500 byte array with the "Initialize Array" function in LabView.  My DLL accepts a void* for this parameter.  As expected, when I connect the output of the Initialize Array to the void* parameter of my DLL, the link breaks.  What LabView function do I need to use to get the address to the array and pass it to my DLL?

 

I can change the parameter type from void* to something else if it makes more sense.  Just not sure what LabView is trying to pass to it.  Once I figure out how to pass the address of an array, I'll start building my specific structures. 

0 Kudos
Message 6 of 39
(4,280 Views)

Well you simply configure the parameter in the CLN to be a byte array, passed as array pointer. The CLN configuration defines what LabVIEW should make of the parameter, not how you created the C code to look like. So if you want to pass an array you have to configure an array and if you want to pass the data pointer (instead of the LabVIEW array handle) you configure that in such a way too). If the DLL wants to treat it as void*, char*, mystruct* or whatever is completely beyond the scope of the CLN configuration.

 

Of course it is handy if the CLN configuration and the way the C function treats the parameter are compatible with each other in order to avoid crashes, but the CLN configuration really is only to tell LabVIEW how it should pass that parameter and nothing else.

 

And if you invest a little more time on the LabVIEW side to create a cluster that has the same layout as your C structure, you can go even further. Configure the CLN parameter to "Adapt to type" and wire the cluster directly to the parameter and you are all set. This will pass the pointer to the memory the cluster is occupying.

Rolf Kalbermatter  My Blog
DEMO, Electronic and Mechanical Support department, room 36.LB00.390
0 Kudos
Message 7 of 39
(4,275 Views)

I found my confusion.  I had assumed that LabView parsed my header file correctly and set my inputs correctly.  I assumed incorrectly.  LabView set my void* parameter to I32.  I changed the parameter in Call Library Function to "Unsigned Pointer-sized Integer", and set the containing VI to U8.  Then I type cast my array to U8, and it runs.

 

Now I just have to figure out how to view an adhoc display of my returned buffer.  Like a spreadsheet like display in hex format.  I type cast my returned buffer back to a U8 array.  Not I'm just trying to figure out what indicator I can use to display it.

0 Kudos
Message 8 of 39
(4,269 Views)

Why so complicated? If you pass a pointer sized integer you only pass the pointer itself. That is nice for opaque pointers such as handles that you do not to look at in LabVIEW itself but simply pass to other API functions through the CLN.

 

But here you want to look at the data so it is much better to use a datatype that you can look at in LabVIEW. A byte array buffer is one possibility, which could be then viewed in an array indicator or converted to a string and viewed in a string indicator. But a cluster would be even more handy in the final solution, as explained in my previous post.

 

Just don't forget that for C API functions the caller is supposed to provide all the memory buffers the callee should fill data into. So in LabVIEW if you go with a byte array you need to allocate it beforehand with the Initialize node. If you use clusters directly, the cluster definition itself is already the memory buffer where the function can fill in its data.

Rolf Kalbermatter  My Blog
DEMO, Electronic and Mechanical Support department, room 36.LB00.390
0 Kudos
Message 9 of 39
(4,264 Views)

By the way, my solution was apparently not correct.  The DLL crashes.  I am using the Initialize Array function allocate my array.  I'm hoping that when I set the numeric input to UB and the size to 1500, the output array is equivalent to:

 

char *buffer = new char[1500];

 

I changed the parameter to unsigned 8-bit byte passed by reference.  In the sub-VI, I set the incoming data to U8.  Not really sure how to specify that its an array.  When I try to connect the output from Initialize Array to my DLL sub-VI, the wire breaks due to incompatible type.  So, I use the type case function.  I think I need to set the incoming data in the DLL sub-VI to something more appropriate.  Any recommendations?

 

My solution above still crashes though. 

0 Kudos
Message 10 of 39
(4,258 Views)