Click here to Skip to main content
15,663,632 members
Please Sign up or sign in to vote.
5.00/5 (1 vote)
See more:
Hi folks!

I have to send and receive data via TCP/IP from a legacy server. The bytes I send and receive are of course representing some data structures. In C/C++ I would memcpy the array into an existing structure or I would just cast a pointer of the strcut type to my byte array. In C it would look something like this:
C++
#pragma pack(push, 1)

typedef struct INNER_ST
{
    DWORD A;
    BYTE B;
};

typedef struct FOO_ST
{
    WORD W;
    BYTE X[20];
    INNER_ST data[10];
};

#pragma pack(pop, 1)

void ReceiveData(const BYTE *pData)
{
    FOO_ST *pFooSt;

    pFooSt = (FOO_ST *)pData;

    DWORD alpha = pFooSt->data[0].A;

}



In C# my structures would look like this:
C#
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct INNER_ST
{
    public UInt32 A;
    public Byte B;
};

[StructLayout(LayoutKind.Sequential, Pack = 1)]
unsafe struct FOO_ST
{
    public UInt16 W;
    public fixed Byte X[20];
    public fixed INNER_ST data[10]; // <- fails, Error CS1663 
    /*
    "Fixed size buffer type must be one of the following: bool, byte, short, int, long, char, sbyte, ushort, uint, ulong, float or double"
    */
};


To copy "simmple" structures like INNER_ST with Marshal.PtrToStructure is not the problem.

My question: What can I do with arrays of structures inside structure to solve error CS1663.

Thx for any ideas or hints.
Andy

PS: Of course I cannot change the server side. I have the header files with the structure definitions in C and the new client will be in C#.
Posted

1 solution

Ignore what I posted previously, I was somewhat overcomplicating things! The method I suggested can be used when an unknown length of data is required to be marshalled.

As you know the length, it's simple:
C#
[StructLayout(LayoutKind.Sequential)]
struct Inner
{
    public uint A;
    public byte B;
}

C#
[StructLayout(LayoutKind.Sequential)]
struct Foo
{
    public ushort W;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)]
    public byte[] X;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)]
    public Inner[] data;
}

Why are you using fixed and unsafe?
 
Share this answer
 
v3
Comments
Andy411 23-Nov-12 4:20am    
My 5. That's it. Thx a lot. You saved my friday :-)
When I started googling about the subject most examples used fixed arrays. That's why I used fixed and unsafe. I also found some examples with the MarshalAsAttribute but they did not suit my needs. I think I also skipped the ByValArray value during reading the documentation. Now it's more clear to me.
One thing left to me is to pay attantion during construction to initialize the arrays:
Foo f = new Foo()
{
x = new byte[20],
data = new Inner[10],
};
DaveyM69 23-Nov-12 13:13pm    
You generally only need to use fixed if the unmanaged function will mutate the data and you need it again afterwards - it prevents the GC moving the data in memory. GCHandle (when using GCHandleType.Pinned) is normally a better way for that though, or Marshal.AllocHGlobal - they both need to be freed if used so beware if you ever need them!
Bachowny 17-Mar-16 17:47pm    
Thanks so much! Sorted me right out.
Anteee 11-May-20 16:58pm    
Time I spent looking for answers and then I find this simple solution. I love you!

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900