Упорядочивание C Struct с массивом структур в нем

Я обращался с подобными вопросами на этом форуме, но не нашел решения своей проблемы.

Я некоторое время боролся с проблемой маршалинга. У меня есть структура, содержащая массив другой структуры. Платформа Win CE. Я использую Visual Studio 2008 и .NET CF 3.5.

Код:

Структуры C:

 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;

Размер структуры MY_SUPPORTED_DATA_RATES составляет 296 байт в C.

Это моя попытка преобразовать его в структуру C#:

Конвертация C#:

    [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;
    };

Здесь я получаю размер 304 байта, используя Marshal.SizeOf(my_supported_rates);

Я безуспешно пробовал следующие вещи:

  • Добавление и удаление различных элементов атрибута в атрибуте MarshalAs в структуре my_supported_rates, например ArraySubType = UnmanagedType.Struct
  • У меня есть Intptr с необходимыми данными, и я попытался преобразовать ptr в структуру, используя код my_supported_rates = (my_supported_rates) Marshal.PtrToStructure(ptr,my_supported_rates.GetType());. Но правильного преобразования не произошло.
  • Некоторые другие предложения в блогах и StackOverflow, которые мне не пригодились.

person arya2arya    schedule 09.04.2014    source источник
comment
У меня нет CE, но ваша структура С# имеет SizeOf 296 в моей настольной программе С#. Кстати, вы должны удалить CharSet = CharSet.Unicode, так как в ваших структурах нет текстовых данных.   -  person David Heffernan    schedule 09.04.2014
comment
@DavidHeffernan Спасибо!! Я удалил CharSet = CharSet.Unicode. Упорядочивание оставшейся структуры не вызывает проблем, не так ли?   -  person arya2arya    schedule 09.04.2014
comment
Как я уже сказал, мне кажется, что все в порядке. Я не понимаю, откуда 304. Это на CE правильно?   -  person David Heffernan    schedule 09.04.2014
comment
@DavidHeffernan да, сэр, на машине WIN CE я получаю Marshal.SizeOf(my_supported_rates); 304 байта   -  person arya2arya    schedule 09.04.2014
comment
Вы имеете в виду Marshal.SizeOf(typeof(...))?   -  person David Heffernan    schedule 09.04.2014
comment
@DavidHeffernan Да, сэр..!!   -  person arya2arya    schedule 09.04.2014
comment
@DavidHeffernan Привет, сэр Можем ли мы Реализовать событие щелчка мышью в компактной среде С# .net WINCE?   -  person arya2arya    schedule 17.04.2014


Ответы (1)


Ваши переводы кажутся мне хорошими. Работая на рабочем столе, а не на CE, я обнаружил, что для этих типов

[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;
};

тот

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

Так что, казалось бы, что-то странное в CE pinvoke marshaller. Возможно, вам придется заставить руку маршала, выполнив следующие действия:

[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;
};

То есть, если LayoutKind.Explicit и FieldOffset поддерживаются на CE.

Если они не поддерживаются, вам нужно выполнить маршалинг вручную. Вы ищете Marshal.AllocHGlobal, а затем Marshal.ReadByte, Marshal.ReadInt16 и так далее.

person David Heffernan    schedule 09.04.2014