LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

How to call LabView function with nested structs and arrays from C#

Hi,
 
I've got the following functions defined in a LabView-dll:
uint32_t __stdcall VOSC04_General(uint32_t Command, TD18Hdl *Messages);
uint32_t __stdcall CheckDiameter(uint32_t Command, TD6 *Parameter);
typedef struct {
 double SP_Diameter;
 double SP_Tolerantie;
 double PV_Diameter;
 } TD6;
typedef struct {
 int32_t dimSize;
 int32_t Numeric[1];
 } TD18;
typedef TD18 **TD18Hdl;

 
I've got some C#-code (generated by PInvoke-wizard) to call these functions:
[DllImport("vosc04.dll")]
public static extern uint32_t VOSC04_General (uint32_t Command, ref TD18Hdl Messages);
[DllImport("vosc04.dll")]
public static extern uint32_t CheckDiameter(uint32_t Command, ref TD6 Parameter);
[StructLayout(LayoutKind.Sequential,Pack=4)]
public struct TD18
{
   public int32_t dimSize;
   [ MarshalAs( UnmanagedType.ByValArray, SizeConst=1)]
   public int32_t [] Numeric;
};
[StructLayout(LayoutKind.Sequential,Pack=4)]
public struct TD6
{
   public Double SP_Diameter;
   public Double SP_Tolerantie;
   public Double PV_Diameter;
};
The problem now is that when I try to read the Messages-output-parameter, I get wrong values (pointers?). I think that the problem lies in the fact that LabView generated a TD18 AND an TD18Hdl struct.
How can I correct this problem?
Can anyone give me some advise to correct this problem? I'm not an expert in C, only in C#.
0 Kudos
Message 1 of 2
(3,365 Views)
I think the problematic line is this:

public struct TD18
{
   public int32_t dimSize;
   [ MarshalAs( UnmanagedType.ByValArray, SizeConst=1)]
   public int32_t [] Numeric;
};

It looks like C# is forcing the array to be of size 1. The thing is, LabVIEW stores arrays as handles which are double pointers to a structure which contains a size element followed by the elements of the array. For your example, int32 arrays are stored in memory as:

handle -> location -> |size|element 1|element 2| .... |element size-1|

Because C does not do runtime array bounds checking, you can get away by declaring the structure as:

typedef struct {
 int32_t dimSize;
 int32_t Numeric[1];
 } TD18;

The correct declaration would've been:
typedef struct {
 int32_t dimSize;
 int32_t Numeric[size];
 } TD18;

But size is not a constant, so C/C++ won't let you do that. So, even though the array is declared to be of size 1, it can (and usually does) have more than 1 element. This does not cause a problem because LabVIEW allocates memory based on the actual size of the array.

If I were you, I'd try to change the prototype of the LabVIEW DLL function to accept a pointer to array data, rather than an array handle, pre-allocate memory for the array in C# and pass a pointer to the allocated memory into LabVIEW so that LabVIEW can "fill it up".

Let me know if you need more information.

Pramod
0 Kudos
Message 2 of 2
(3,303 Views)