2016年9月24日土曜日

C#でのboolのサイズについて(Managed、UnManaged、Marshal)

Windowsでのboolって、昔からいろいろと厄介なことがあります。(サイズ間違えたり、サイズ間違えたり・・・)
というわけで、少しまとめてみました。

結論から書くと、C++からC#へのデータの受け渡し時には
bool:「MarshalAs( UnmanagedType.U1)」
BOOL:「MarshalAs( UnmanagedType.Bool)」

ってことを言いたいだけです。

VisualC++(UnManaged)


VisualC++の時代から、BOOLとboolで違いがあることは、皆さんよくご存じだと思います。

bool:1byte
BOOL:4byte

この理由自体は、単純で、"minwindef.h"を見れば、すぐわかると思います。

typedef int                 BOOL;

BOOL自体は、intなので、4バイトになります。


C#(Managed)


C#になって、違いがなくなりました。

bool:1byte
System.Boolean:1byte


Marshal


では、C++とC#でデータのやり取りをする場合は、どうなってしまうのか。

Marshal.SizeOfで、サイズを確認してみたいと思います。



Marshal.SizeOf(bool):4byte
Marshal.SizeOf(Boolean):4byte

結果は「4バイト」です。そのため、dllimportした場合や、PtrToStructureなど、C++からC#にデータをコピーする場合には、注意が必要になります。
C++の構造体で、boolを使用している場合には、意図的に、「1バイトだよ」と教えてあげる必要があります。(Marshal時には、デフォルトで、「UnManagedType.Bool」がデフォルトとなっています。)
そのために意図的に「MarshalAs( UnmanagedType.U1)」を指定する必要があります。

以下の構造体の例を見てます。

[StructLayout(LayoutKind.Sequential,Pack =1)]
struct boolStruct
{
    bool value;
}
[StructLayout( LayoutKind.Sequential, Pack = 1 )]
struct boolStructU1
{
    [MarshalAs( UnmanagedType.U1)]
    bool value;
}
class Program
{
    static void Main( string[] args )
    {
        Console.WriteLine( "boolStruct:{0}byte",
            Marshal.SizeOf( typeof(boolStruct) ) );
        Console.WriteLine( "boolStructU1:{0}byte",
            Marshal.SizeOf( typeof( boolStructU1 ) ) );
    }
}

結果:
boolStruct:4byte
boolStructU1:1byte
皆様、C++とのデータのやり取りでboolを使用する場合にはお気を付けください。

参照:

0 件のコメント:

コメントを投稿