LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Running a DLL function with a structure pointer parameter

Solved!
Go to solution

Hello,

 

The two DLL functions I need to use with Call Library Function Nodes in a VI are described below. I used generic names here for readability.

 

NI Forum DLL.png

 

Node parameter settings I set for each function are shown below.

 

NI Forum CreateObj.png

 

NI Forum Init.png

 

(1) Do you find any incorrect settings? I am quite new to this.

 

(2) How do you create a pointer to the structure for arg5? I created a cluster of 10x I32 elements and 4x arrays of 512x I32 elements. How do I create its pointer to feed into arg5? Do I need some wrapper to take the cluster by value and create a pointer?

 

Thank you.

 

0 Kudos
Message 1 of 10
(478 Views)

1) It seems ok after a brief glance

 

2) You did not give enough information to say for sure. Show the actual declaration of the structure and function prototype! You seem to go to great lengths to try to obfuscate what hardware this is about. But while the C syntax often isn’t enough to describe an API fully, replacing the syntax through prosa text entirely isn’t very efficient either.

LabVIEW arrays never translate directly to C array pointers, but you can configure a Call Library parameter to let LabVIEW do the necessary conversions but not when they are inside clusters. It “seems” your arrays are in fact fixed size which makes them inlined in the structure and not a pointer, but I want to see the actual declaration before explaining more!

Rolf Kalbermatter
My Blog
Message 2 of 10
(421 Views)

Thank you for your comment, rolfk. It would take some time to get the header file from the original author of the DLL. What would be the recommended solution if we assume the arrays are inlined in the structure?

 

In the meantime, I came across some posts mentioning LabVIEW Manager functions such as DSNewPtr, MoveBlock and DSDisposePtr. Would these be relevant here?

0 Kudos
Message 3 of 10
(375 Views)

@Arcanix wrote:

Thank you for your comment, rolfk. It would take some time to get the header file from the original author of the DLL. What would be the recommended solution if we assume the arrays are inlined in the structure?

That would be simply a single array of 10 + 4 * 512 Int32 elements, passed as a C array pointer. Insert the data at the correct offsets:

0 - 9: for the first 10 elements

10+: for the first array

522+: for the second array

1034+: for the third array

1546+: for the forth array

 

Make sure the array is really 2058 elements large just to make sure!

 

In the meantime, I came across some posts mentioning LabVIEW Manager functions such as DSNewPtr, MoveBlock and DSDisposePtr. Would these be relevant here?


That is not going to help assuming all your arrays are really fixed size and hence inlined.

Rolf Kalbermatter
My Blog
0 Kudos
Message 4 of 10
(364 Views)

Here is another function 'Run' in the same DLL. The structure here includes multiple types of members.

 

NI Forums DLL 2.png

 

That tells me we cannot treat the structures in this DLL as arrays. What would be the 'standard' way to pass these structure pointers to Call Library Function Nodes?

0 Kudos
Message 5 of 10
(232 Views)

Well you still could maybe represent them as an array but would have to treat the parts differentely. However there is something very fishy about that documentation.

 

MeasData consists of 47 members

unsigned char

long

unsigned long

unsigned short

array of 512 longs

array of 512 floats

 

That's according to my counting only 6 members (or 1028 if you count array elements separately!!

 

Rolf Kalbermatter
My Blog
0 Kudos
Message 6 of 10
(193 Views)

Just an short information as I have had this some times. 

 

In my case it was a SIZE problem of the Struct in Labview.

When you place an array and other objects into a LabVIEW cluster the actual size is not just the number of expected elements but LV always adds some size for the arrays.

 

In my case I made a "sub cluster" representing the elements in the array and therefore the correct size.

Finally the full size is correct and all works as expected.

 

I know it is a nasty work and does not look nice on the FP depending on the arraysize, but it works.

Gernot Hanel
IONICON Analytik Gesellschaft m.b.H.
0 Kudos
Message 7 of 10
(87 Views)

@nottilie wrote:

Just an short information as I have had this some times. 

 

In my case it was a SIZE problem of the Struct in Labview.

When you place an array and other objects into a LabVIEW cluster the actual size is not just the number of expected elements but LV always adds some size for the arrays.

 

In my case I made a "sub cluster" representing the elements in the array and therefore the correct size.

Finally the full size is correct and all works as expected.

 

I know it is a nasty work and does not look nice on the FP depending on the arraysize, but it works.


That's at best confusing information. The difference is if the array inside the structure is fixed size or not. If it is fixed size, the C compiler "inlines" it in the structure. Otherwise it is simply a pointer to the data elsewhere.

 

A LabVIEW array is a handle, which is basically a pointer to a pointer to a memory area with an int32 per dimension in the beginning, indicating the size of the according dimension, and the number of elements follows after that. As you can see, in C it is either inlined or a pointer to the data. In LabVIEW it is a pointer to a pointer to a buffer containing the size AND the data. There is no way to simply "coerce" the LabVIEW array into either of these two.

 

But for inlined C arrays you can represent them with an according cluster with the correct amount of elements in there as you correctly describe. But that has nothing to do with the additional size integer in front of the LabVIEW array buffer!

 

Or as in the first problem in this thread, you can simply treat it as an array anyways with the correct amount of elements and here you can configure the Call Library Node to pass the actual pointer to the array. But you can't configure the Call Library Node to convert arrays inside a cluster. Adding that option to the Call Library Node configuration dialog for sure would make that dialog so complicated that absolutely nobody could use it anymore.

 

And of course to make matters even more interesting you also have something called memory alignment. That means that the C compiler inserts dummy filler bytes between structure elements to make each element align to its natural memory address, which depends on the size of the element. Most CPUs, except the Intel x86 architecture, are not happy if the program tries to access a memory location that is not aligned to its element size.

And the alignment in LabVIEW 32-bit for Windows does not match the default alignment of C compilers as is used nowadays.

 

Rolf Kalbermatter
My Blog
0 Kudos
Message 8 of 10
(75 Views)

Sorry for the confusion.

 

I just wanted to explain this example in words which obviously ended in the confusion:

 

In c++ I have  a structure needed for a DLL call defined like this.

struct ADQInfoListEntry
{
enum ADQHWIFEnum HWIFType;
enum ADQProductID_Enum ProductID;
unsigned int VendorID;
unsigned int AddressField1;
unsigned int AddressField2;
char DevFile[64];
unsigned int DeviceInterfaceOpened;
unsigned int DeviceSetupCompleted;
};

 

To have the matching structure in LV I needed to produce this. (the char DevFile[64] is a cluster and not an array !).

nottilie_0-1749036481660.png

 

 

Gernot Hanel
IONICON Analytik Gesellschaft m.b.H.
Message 9 of 10
(64 Views)
Solution
Accepted by Arcanix

@rolfk wrote:

Well you still could maybe represent them as an array but would have to treat the parts differentely. However there is something very fishy about that documentation.

 

MeasData consists of 47 members

unsigned char

long

unsigned long

unsigned short

array of 512 longs

array of 512 floats

 

That's according to my counting only 6 members (or 1028 if you count array elements separately!!

 


That is a list of data types used in the structure. There are multiple unsigned char members and so on.

 

In the meantime, I could check how InitData structure is defined. It was as expected. MAX_CAN_COUNT_SIZE is 512.

 

struct InitData {

   long lAuxTCnt;
   long lAuxVCnt;
   long lAuxThCnt;
   long lAuxHCnt;
   long lAuxGasCnt;
   long Reserved1;
   long Reserved2;
   long Reserved3;
   long lCanMasterCnt;
   long lCanSlaveCnt;
   long lDivisionCode1[MAX_CAN_COUNT_SIZE];
   long lDivisionCode2[MAX_CAN_COUNT_SIZE];
   long lDivisionCode3[MAX_CAN_COUNT_SIZE];
   long lCanDataType[MAX_CAN_COUNT_SIZE];

};

 

I was able to make the DLL function work. Since 'Array To Cluster' can create a cluster of only up to 256 elements, I used 'Type Cast' to convert each array into a cluster of size 512. For typecasting type input, I still used 'Array To Cluster' to create a cluster of 256 elements and copy-and-pasted them to create a cluster of 512 elements quickly.

NI Forum Init Data.png

 

 

NI Forum Init arg5.png

 

Thank you, folks!

0 Kudos
Message 10 of 10
(24 Views)