LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Setting up a call library node for a DLL

Solved!
Go to solution

Hello, I am attempting to wire up my dll to labview but I am having trouble doing so. I have tried using the wizard but it does not seem to like the dll's header file: 

torresh87_1-1574795620346.png

 

My question is can I even set/return these structures in LabVIEW?

While setting up vpt_dll_req_t in the call library function I used Adapt to Type and Handles by Value. 

torresh87_0-1574794179857.png

 

When I create the labview c file it shows this: 

 

torresh87_2-1574795804838.png

 

I believe this means it is passing the buf(array as a pointer(TD4, TD2). Is that correct? 

 

Any help is appreciated, thank you for reading my post. 

 

torresh87_3-1574795985546.png

0 Kudos
Message 1 of 35
(3,772 Views)

It's hard to say without the prototype of the function (did I miss it?).

 

We also can't see the data types of the cluster elements. They should match.

 

The array is empty, a 256 byte array is expected. So, make the array (at least) 256 elements...

 

You'd have to predefine the output cluster as well. The point of passing the cluster (most notably the array) is that the dll doesn't have to allocate data*. So passing an empty cluster (empty array) will fail. Predefine the cluster's data, so the dll can fill it.

 

* If the dll was to allocate memory (data), who would be responsible for deallocating it? The code would either leak, crash, or be more complex.

0 Kudos
Message 2 of 35
(3,720 Views)
Solution
Accepted by topic author torresh87

A LabVIEW array embedded in a cluster is NOT the same thing as a fixed-size C array inside a struct. There are two reasonable ways to approach this in LabVIEW:

1) make the "buf" element of the cluster into a cluster containing 256 U8 elements, replacing the array. This gets you a fixed-size element equivalent to the 256-element C array. You'll probably find the "array to cluster" function helpful for creating such a cluster, since it allows you to enter the number of elements, then create a constant or control from it.

OR

2) Instead of passing in a LabVIEW cluster, pass in an array of 4 * 4 bytes (uint32) + 8 bytes (double) + 256 bytes = 280 bytes. Use initialize array to create an array of the correct size. Then pull out the particular array elements you care about, being careful about endianness for the multi-byte values.

0 Kudos
Message 3 of 35
(3,702 Views)

Hello wiebe@carya, 

 

Thank you for your response. 

 

Sorry I left out the function prototype: 

 

void api( vpt_dll_req_t*,  vpt_dll_rtn_t* );

I have not preset both the input and output clusters, I also set the array size(cluster size to 256) as you suggested. 

I am able to communicate with the device. 

 

torresh87_0-1574884532735.png

 

Unfortunately just as you mentioned the code is crashing very randomly.

" * If the dll was to allocate memory (data), who would be responsible for deallocating it? The code would either leak, crash, or be more complex." 

 

If I remember correctly I believe I can have labview dellocate the memory? 

 

Any thoughts on how to proceed? 

 

Thank you for all your help. 

 

0 Kudos
Message 4 of 35
(3,689 Views)

 

 

PROVEN ZEALOT, 

 

Thank you so much as you suggested I went with option 1.

 

And the vi is communicating properly with my device. 

Unfortunately Labview is crashing very randomly. Any idea how I can debug this? 

 

torresh87_0-1574885987418.png

0 Kudos
Message 5 of 35
(3,687 Views)

Is it always crashing when you make the call to the DLL, or somewhere else? How is the call library function node configured? Try setting the debug level to maximum. Is the calling convention (C or WinAPI) correct?


I don't think your attempt to insert a null in the last element of the array is working: you're inserting at index 256, and an array of 256 elements only goes up to index 255 (0-indexing). But the code should already insert 0's at every byte past the end of the string anyway, unless your string is longer than 256 characters, so there's no need to do this explicitly.

0 Kudos
Message 6 of 35
(3,682 Views)

@nathand wrote:

2) Instead of passing in a LabVIEW cluster, pass in an array of 4 * 4 bytes (uint32) + 8 bytes (double) + 256 bytes = 280 bytes. Use initialize array to create an array of the correct size. Then pull out the particular array elements you care about, being careful about endianness for the multi-byte values.


This would have been my next suggestion.

 

Arrays in clusters are probably preceded with the array size, something C/C++ doesn't expect. The dll function will change this size (assuming it's the first element) and LabVIEW won't be able to deal with that.

 

You should be able to cast the cluster form\to an array of bytes, but you should probably swap the bytes and words of the cluster to take care of the endianness.

 

0 Kudos
Message 7 of 35
(3,655 Views)

@torresh87 wrote:

" * If the dll was to allocate memory (data), who would be responsible for deallocating it? The code would either leak, crash, or be more complex." 

 

If I remember correctly I believe I can have labview dellocate the memory? 


LabVIEW won't do that automatically. The dll can allocate memory in several ways (local heap, global heap, some custom memory manager, for example) and LabVIEW would need to deallocate using the expected method. You usually need more than just a memory pointer. For a heap allocation, you need the heap handler and the pointer to deallocate. The dll has that information, LabVIEW doesn't.

 

You can 'manually' allocate memory in LabVIEW with the external code functions (DS\AZ functions), but this would do exactly the same as a initialize array in a more complicated way. The initialize array is deallocated automatically, the manual allocation needs to be deallocated manually.

0 Kudos
Message 8 of 35
(3,654 Views)

Some of the comments in this thread are less than 100% accurate.

 

While a DLL can allocate memory that can't play here. The two buffers are passed as pointer and not as reference to a pointer so there is absolutely no way that the function could return any allocated pointers somehow.

 

The API is fairly simply with only the inlined 256 byte string being a minor difficulty. My guess (because the OP forgot to append his VI so we could check) is that the Array To Cluster node is still using the default size of 9 elements despite the comment in the diagram indicating otherwise. You can make the array in front of the Array To Cluster as big as you like, it will always be resized to the size configured in the right click menu of that node! In fact you could simply forget the Array resize altogether and just make sure that if the incoming string is biggger than 255 characters to replace the array element at index 255 with a NULL byte to make sure the string is properly NULL terminated then pass it through the Array To Cluster node which has been properly setup to create 256 element cluster. If the string is smaller than 256 characters, the Array To Cluster node will always append the necessary 0 elements to make it the size needed as it was configured.

 

A two small buffer is almost the only thing that could occasionally crash for this function. If the calling convention was wrong it would crash at every call!

Rolf Kalbermatter
My Blog
Message 9 of 35
(3,622 Views)

@rolfk wrote:

Some of the comments in this thread are less than 100% accurate.

 

While a DLL can allocate memory that can't play here. The two buffers are passed as pointer and not as reference to a pointer so there is absolutely no way that the function could return any allocated pointers somehow.

 

The API is fairly simply with only the inlined 256 byte string being a minor difficulty. My guess (because the OP forgot to append his VI so we could check) is that the Array To Cluster node is still using the default size of 9 elements despite the comment in the diagram indicating otherwise. You can make the array in front of the Array To Cluster as big as you like, it will always be resized to the size configured in the right click menu of that node! In fact you could simply forget the Array resize altogether and just make sure that if the incoming string is biggger than 255 characters to replace the array element at index 255 with a NULL byte to make sure the string is properly NULL terminated then pass it through the Array To Cluster node which has been properly setup to create 256 element cluster. If the string is smaller than 256 characters, the Array To Cluster node will always append the necessary 0 elements to make it the size needed as it was configured.

 

A two small buffer is almost the only thing that could occasionally crash for this function. If the calling convention was wrong it would crash at every call!


wouldn't casting a cluster to an array and than back avoid all this?

0 Kudos
Message 10 of 35
(3,617 Views)