none
Размер структуры для взаимодействия с unmanaged кодом RRS feed

  • Вопрос

  • В C# проекте используется вызов функции из C++ dll.

    Сигнатура функции такая bool GetParams( char *name, ParamsInfo *info); name - используется как входной параметр, info - как выходной.

    Используемая структура описана так:

    enum State {STBY, WORK, FLT};
    
    struct ParamsInfo
    {
        bool active;
        bool used;
        State state;
        unsigned char rs;
        unsigned char rw;
        unsigned char fw;
        bool pr;
        bool nr;
        bool lod;
        bool ptt;
        unsigned int channel;
    };

    sizeof(ParamsInfo) == 14

    В C# функция подключена так:

    [DllImport(@"library.dll", EntryPoint = "_GetParams", CallingConvention = CallingConvention.Cdecl)]
    private static extern bool GetParams(string name, out ParamsInfo info);

    А структура так:

    public enum ContrState : byte {STBY, WORK, FLT};
    
    [StructLayout(LayoutKind.Explicit,Pack=1)]
    public struct ParamsInfo
    {
                [FieldOffset(0)]
                public bool active;
                [FieldOffset(1)]
                public bool used;
                [FieldOffset(2)]
                public ContrState state;
                [FieldOffset(3)]
                public byte rs;
                [FieldOffset(4)]
                public byte rw;
                [FieldOffset(5)]
                public byte fw;
                [FieldOffset(6)]
                public bool pr;
                [FieldOffset(7)]
                public bool nr;
                [FieldOffset(8)]
                public bool lod;
                [FieldOffset(9)]
                public bool ptt;
                [FieldOffset(10)]
                public uint channel; 
    }

    Время от времени возникает StackOverflowException, приводящий порой даже к BSOD. В связи с чем у меня пара вопросов:

    1) Почему чтобы добиться в C# размера структуры в 14 байт пришлось использовать

    [StructLayout(LayoutKind.Explicit,Pack=1)]

    с указанием смещения для каждого поля. Хотя, как мне казалось, должно было быть достаточно

    [StructLayout(LayoutKind.Sequential,Pack=1)]

    Но если так сделать, то размер получается 32 байта (Определяю как Mashal.SizeOf() )

    2) Значения полей передаются правильно частично. Изменяя например поле nr - в C# приходит как pr, т.е. как будто в структуре другое смещение используется. Но несмотря на это последнее поле channel приходит как надо. Чем это может быть обусловлено?

    Спасибо.


    12 марта 2012 г. 12:26

Ответы

  • Оказалось, что bool интерпретируется в таком случае как 4х-байтовое значение. Добавление атрибута
    [MarshalAs(UnmanagedType.I1)]
    к полям и возвращаемому значению типа bool решило проблему с размерами. Со стеком проблема при этом осталась.

    • Изменено tulosba 12 марта 2012 г. 13:59
    • Помечено в качестве ответа Abolmasov Dmitry 14 марта 2012 г. 8:03
    12 марта 2012 г. 13:37
  • Проблема со стеком решилась: см тут
    • Помечено в качестве ответа tulosba 13 марта 2012 г. 14:17
    13 марта 2012 г. 14:17

Все ответы

  • Оказалось, что bool интерпретируется в таком случае как 4х-байтовое значение. Добавление атрибута
    [MarshalAs(UnmanagedType.I1)]
    к полям и возвращаемому значению типа bool решило проблему с размерами. Со стеком проблема при этом осталась.

    • Изменено tulosba 12 марта 2012 г. 13:59
    • Помечено в качестве ответа Abolmasov Dmitry 14 марта 2012 г. 8:03
    12 марта 2012 г. 13:37
  • Проблема со стеком решилась: см тут
    • Помечено в качестве ответа tulosba 13 марта 2012 г. 14:17
    13 марта 2012 г. 14:17