Marshalling C Struct with array of structures in it

吃可爱长大的小学妹 提交于 2019-12-02 03:19:57

问题


I referred the similar questions in this forum but didn't get the solution for my problem.

I have been struggling with marshaling problem for a while. I have a structure that contains an array of another structure, The platform is Win CE. I am using Visual Studio 2008 and .NET CF 3.5.

The code:

C Structures:

 struct dot11Rate
 {
    unsigned int rate;
    unsigned char mode; 
 };

 typedef struct my_supported_rates
 {
    unsigned short n_rates;
    struct dot11Rate srates[36];
    unsigned char  isSet;
    unsigned char no_of_HTStreams;
 }MY_SUPPORTED_DATA_RATES;

Size of the struct MY_SUPPORTED_DATA_RATES is 296 bytes in C

This is my attempt to convert it into a C# struct:

C# Converted:

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
    public struct dot11Rate
    {
        public uint rate;
        public byte mode; /* HT=1, non-HT=0*////
    };

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
    public struct my_supported_rates
    {       
        public ushort n_rates;
        [MarshalAs(UnmanagedType.ByValArray,SizeConst = 36)]
        public dot11Rate[] srates;
        public byte isSet;
        public byte no_of_HTStreams;
    };

Here I am getting the size as 304 bytes using Marshal.SizeOf(my_supported_rates);

I have tried the following things without any success:

  • Adding and removing various attrubute elements in MarshalAs attribute in my_supported_rates struct such as ArraySubType = UnmanagedType.Struct
  • I have Intptr with required data and I tried to convert ptr to the struct using the code my_supported_rates = (my_supported_rates) Marshal.PtrToStructure(ptr,my_supported_rates.GetType());. But proper conversion is not happend.
  • Some other suggestions on blogs and StackOverflow which didn't prove useful to me

回答1:


Your translations look good to me. Running on desktop rather than CE I find that, for these types

[StructLayout(LayoutKind.Sequential)]
public struct dot11Rate
{
    public uint rate;
    public byte mode;
};

[StructLayout(LayoutKind.Sequential)]
public struct my_supported_rates
{       
    public ushort n_rates;
    [MarshalAs(UnmanagedType.ByValArray,SizeConst = 36)]
    public dot11Rate[] srates;
    public byte isSet;
    public byte no_of_HTStreams;
};

that

Marshal.SizeOf(typeof(my_supported_rates)) == 296

So it would seem to be something odd in the CE pinvoke marshaller. You might need to force the hand of the marshaller by doing this:

[StructLayout(LayoutKind.Explicit, Size=296)]
public struct my_supported_rates
{       
    [FieldOffset(0)]
    public ushort n_rates;
    [FieldOffset(4)]
    [MarshalAs(UnmanagedType.ByValArray,SizeConst = 36)]
    public dot11Rate[] srates;
    [FieldOffset(292)]
    public byte isSet;
    [FieldOffset(293)]
    public byte no_of_HTStreams;
};

That is, if LayoutKind.Explicit and FieldOffset are supported on CE.

If they are not supported then you'll need to marshal by hand. You are looking for Marshal.AllocHGlobal and then Marshal.ReadByte, Marshal.ReadInt16 and so on.



来源:https://stackoverflow.com/questions/22964241/marshalling-c-struct-with-array-of-structures-in-it

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!