具有另一个结构的固定大小数组的结构

时间:2013-02-25 16:36:46

标签: c# arrays winapi struct

如何在C#中使用另一个结构的固定大小的数组声明一个结构?我需要this声明它才能正常工作。或者如果我想创建bitmapinfo(-header),我的方法是错误的吗?

[StructLayout(LayoutKind.Sequential)]
public struct RGBQUAD
{
    public byte b;
    public byte g;
    public byte r;
    public byte reserved;
}

[StructLayout(LayoutKind.Sequential)]
public struct BITMAPINFO
{
    public BITMAPINFOHEADER bmiHeader;
    [MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.LPStruct, SizeConst = 1)]
    public RGBQUAD[] bmiColors;
}

修改:我自学了一点UnmanagedType.ByValArraySizeConst = 1对于保持BITMAPINFO编组大小始终为44字节事件非常重要256个大小的RGBQUAD数组。

编辑2:但是SizeConst不能小于实际的数组大小,否则非托管代码可能会使应用程序崩溃。

2 个答案:

答案 0 :(得分:3)

如评论中所述,在C#中,您无法在结构中创建固定大小的结构数组。

但那不是你想要的。在声明中

typedef struct tagBITMAPINFO {
    BITMAPINFOHEADER bmiHeader;
    RGBQUAD          bmiColors[1];
} BITMAPINFO, *PBITMAPINFO;

bmiColors被声明为固定长度的数组,但它实际上是RGBQUAD的可变长度数组的占位符。数组的实际长度取决于bmiHeader.biClrUsed的值in a slightly complicated way

如何在C#中处理此问题完全取决于您对BITMAPINFO结构的处理方式。

<强>更新

我刚看到你的另一个问题。您已将BITMAPINFO传递给SetDIBits,并且您的颜色表始终有256个条目。因此,在BITMAPINFO.bmiColorsSizeConst设置为256。

的声明中

答案 1 :(得分:3)

不幸的是(和IMHO有点令人惊讶地认为.net的设计目标之一是促进与COM的互操作).net运行时不了解除独立System.Array对象或角色之外的任何类型的数组内置于System.String的数组。虽然C#提供fixed数组类型,但是这些数组类型是使用指针算法操作的,其方式是.net运行时不能理解且无法验证。

通过使用元素a0a1a2等定义结构并编写使用的索引属性,可以创建行为类似于固定大小数组的内容。一个switch语句或其他这样的构造来访问它的元素,但是这样的构造可能比正常的数组执行得慢得多。

如果您不需要使用safe代码(并且鉴于您可能与可能不受信任的托管代码进行互操作,“安全”代码可能不是一个考虑因素)我建议您使用显式布局定义RGBQUAD,将int与其他数据重叠,然后让其他结构包含fixed int[whateverSize];来保存RGB数据。它的索引访问器应该能够通过读/写“int”成员来有效地将int转换为RGBQUAD