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

本文关键字:结构 小数 数组 另一个 | 更新日期: 2023-09-27 18:00:55

如何在C#中用另一个结构的固定大小数组声明一个结构?我需要声明这一点,这样它才能工作。或者,如果我想要创建位图信息(-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;
}

编辑:我自己学到的是,如果我分配256大小的RGBQUAD数组,UnmanagedType.ByValArraySizeConst = 1在保持BITMAPINFO封送大小恒定为44字节事件方面非常重要。

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

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

不幸的是(鉴于.net的设计目标之一是促进与COM的互操作,IMHO有点令人惊讶(,.net运行时对任何类型的数组都不了解,除了独立的System.Array对象或System.String中内置的字符数组。尽管C#提供了fixed数组类型,但这些类型是使用指针算术操作的,而.net运行时并不真正理解,也无法验证。

通过定义具有元素a0a1a2等的结构,并编写索引属性,该索引属性使用switch语句或其他此类构造来访问其元素,可以创建行为类似于固定大小数组的东西,但此类构造的执行速度可能比普通数组慢得多。

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

正如注释中所指出的,在C#中,您不能在结构中创建固定大小的结构数组。

但这不是你想要的。在申报中

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

CCD_ 15被声明为固定长度数组,但它实际上是CCD_ 16的可变长度数组的占位符。数组的实际长度取决于(以稍微复杂的方式(bmiHeader.biClrUsed的值。

在C#中如何处理这个问题完全取决于您对BITMAPINFO结构所做的操作。

更新

我刚刚看到你的另一个问题。您正在将BITMAPINFO传递给SetDIBits,并且您的颜色表总是有256个条目。因此,在BITMAPINFO.bmiColors的声明中将SizeConst设置为256。