C#: marshalling a struct that contains arrays

For the arrays, try to use the fixed keyword:

public fixed byte DeviceInfo[MAX_LINK_DEVINFO];
public fixed byte Reserved[40];

whenever I initialize the struct the Name, DeviceInfo, and Reserved fields are all set to null

This is correct, and your definition looks OK to me (BTW, you don't need [MarshalAs] on the primitive fields, the default behaviour is to do what you specified there). Because your array fields are null, the marshaler won't do anything about them when marshaling your struct to unmanaged memory, but it's going to create the strings and arrays when unmarshaling.


What Anton Tykhyy says is correct. I just want to clarify with some examples. Using 'fixed' works, but that forces you to use 'unsafe' as well. I like to avoid using unsafe wherever possible. Using Marshal is a way to get around that.

First, let's say that I have a library that was created in C with the following definitions.

typedef struct {
    int messageType;
    BYTE payload[60];
} my_message;

/**
* \param[out] msg    Where the message will be written to
*/
void receiveMessage(my_message *msg);

/*
* \param[in] msg    The message that will be sent
*/
void sendMessage(my_message *msg);

In C#, the following structure would be equivalent to the one in C.

[StructLayout(LayoutKind.Sequential, Size = 64), Serializable]
struct my_message
{
    int messageType;
    [MarshalAs(UnmanagedType.ByValArray,SizeConst = 60)]
    byte[] payload;

    public initializeArray()
    {
        //explicitly initialize the array
        payload = new byte[60];
    }
}

Since the msg in receiveMessage() is documented as [out], you don't need to do anything special to the array in the structure before passing it to the function. i.e.:

my_message msg = new my_message();
receiveMessage(ref msg);
byte payload10 = msg.payload[10];

Since the msg in sendMessage() is documented as [in], you will need to fill the array before calling the function. Before filling the array, the array needs to be explicitly instantiated before using it. i.e.:

my_message msg = new my_message();
msg.initializeArray();
msg.payload[10] = 255;
sendMessage(ref msg);

Calling initializeArray() should instantiate the array in the previously allocated space created within the struct for this array.