Search code examples
c#c++pinvokemarshalling

Marshalling array of struct from C# to VC++


I'm trying to marshal an array of structs from C# to VC++.

The C++ function looks like this:

void myFunc(tFileListEntry* fileList);

And tFileListEntry is defined as:

typedef struct FILE_LIST
{
    uint16_t FileGroupCounter;
    uint32_t FileID;
    uint16_t NumbSamples;
} tFileListEntry;

In C# I declared the function like this:

[DllImport("MyLib", EntryPoint = "myFunc", CallingConvention = CallingConvention.Cdecl)]
public static extern void myFunc( [In, MarshalAs(UnmanagedType.LPArray)] tFileListEntry[] fileList);

And tFileListEntry is defined as:

[StructLayout(LayoutKind.Sequential)]
public class tFileListEntry
{
    public tFileListEntry(UInt16 fileGroupCounter, UInt32 fileId, UInt16 numbSamples)
    {
        FileGroupCounter = fileGroupCounter;
        FileID = fileId;
        NumbSamples = numbSamples;
    }

    public UInt16 FileGroupCounter;
    public UInt32 FileID;
    public UInt16 NumbSamples;
}

I can set a breakpoint in the C# code as well as in the C++ library. On the managed side the values look right, but on the unmanaged side I get only garbage.

I verified with Marshal.SizeOf() (in C#) and sizeof() (in C++) that the size of the struct is 12 bytes on both sides, so I don't think that padding/packing is an issue here.

What am I doing wrong?


Solution

  • I think the problem here is that on the C# side you have declared it as a class, not as a struct.

    That means when you create the array on the C# side, each element of the array is a reference (4 or 8 bytes depending on the archtecture) not a struct (12 bytes), with the results you are seeing.

    Try changing the C# class to struct.