Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

StructLayout Pack=1 doesn't work with bool?

Quiz: what does the following program print?

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();            
        }
    }
}

Answer:

8
5

This is very confusing to me. Both bool and byte have a size of 1 byte, and specifying [StructLayout(LayoutKind.Sequential, Pack=1)] should nullify any padding issues. Both structs should be 5 bytes. So I have two questions:

  • Why does marshalling work this way?
  • Any workaround? I have 1-byte booleans in native structs I need to import. I can use byte instead of course but it's "messy".

Thanks.

like image 353
Asik Avatar asked Mar 19 '12 07:03

Asik


1 Answers

By default, .NET type bool marshals to unmanaged type BOOL, which is typedefed to int. If you want to marshal to and from 1-byte unmanaged booleans, indicate this to the marshaler with an attribute:

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

Console.WriteLine (Marshal.SizeOf (typeof (Struct3))) ; // prints 5
like image 170
Anton Tykhyy Avatar answered Oct 15 '22 21:10

Anton Tykhyy