Click here to Skip to main content
Rate this: bad
good
Please Sign up or sign in to vote.
See more: C# Unmanaged
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:
#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:
[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 22-Nov-12 4:42am
Andy4112.6K

1 solution

Rate this: bad
good
Please Sign up or sign in to vote.

Solution 1

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:
[StructLayout(LayoutKind.Sequential)]
struct Inner
{
    public uint A;
    public byte B;
}
[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?
  Permalink  
v3
Comments
Andy411 at 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 at 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!

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



Advertise | Privacy | Mobile
Web01 | 2.8.140926.1 | Last Updated 22 Nov 2012
Copyright © CodeProject, 1999-2014
All Rights Reserved. Terms of Service
Layout: fixed | fluid

CodeProject, 503-250 Ferrand Drive Toronto Ontario, M3C 3G8 Canada +1 416-849-8900 x 100