StructLayout Pack = 1 не работает с bool? - PullRequest
9 голосов
/ 19 марта 2012

Тест: что печатает следующая программа?

using System;
using System.Runtime.InteropServices;

namespace ConsoleApplication2 {

    [StructLayout(LayoutKind.Sequential, Pack=1)]
    struct Struct1 {
        bool b;
        int i;
    }

    [StructLayout(LayoutKind.Sequential, Pack=1)]
    struct Struct2 {
        byte b;
        int i;
    }

    class Program {
        static void Main(string[] args) {
            Console.WriteLine(Marshal.SizeOf(typeof(Struct1)));
            Console.WriteLine(Marshal.SizeOf(typeof(Struct2)));
            Console.ReadKey();            
        }
    }
}

Ответ:

8
5

Это меня очень смущает. И bool, и byte имеют размер 1 байт, и указание [StructLayout(LayoutKind.Sequential, Pack=1)] должно свести на нет любые проблемы с заполнением. Обе структуры должны быть 5 байтов. Итак, у меня есть два вопроса:

  • Почему сортировка работает таким образом?
  • Есть обходной путь? У меня есть 1-байтовые логические значения в нативных структурах, которые мне нужно импортировать. Вместо этого я могу использовать байт, но он "грязный".

Спасибо.

Ответы [ 2 ]

18 голосов
/ 19 марта 2012

По умолчанию .NET тип bool отправляется в неуправляемый тип BOOL, что typedef ed до int.Если вы хотите выполнить маршалирование в и из 1-байтового неуправляемого логического значения, укажите это маршалеру с атрибутом:

[StructLayout (LayoutKind.Sequential, Pack=1)]
struct Struct3 {
    [MarshalAs (UnmanagedType.I1)]
    bool b;
    int i;
}

Console.WriteLine (Marshal.SizeOf (typeof (Struct3))) ; // prints 5
2 голосов
/ 19 марта 2012

bool получает значение Marshalled до int32 по причинам совместимости (программы на C / C ++ обычно используют int в качестве логических значений, а в winapi BOOL также typedef редактируется как int), поэтому он конвертируется в 4 байта.

...