1

如何在 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;
}

编辑:我自己学到的是,UnmanagedType.ByValArray如果我分配 256 大小的 RGBQUAD 数组,将BITMAPINFOSizeConst = 1编组大小始终保持在 44 字节事件很重要。

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

4

2 回答 2

3

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

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

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

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

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

更新

我刚刚看到你的另一个问题。您正在传递BITMAPINFOtoSetDIBits并且您的颜色表始终有 256 个条目。所以在声明中BITMAPINFO.bmiColors设置SizeConst为 256。

于 2013-02-25T20:21:35.720 回答
3

不幸的是(鉴于 .net 的设计目标之一是促进与 COM 的互操作,恕我直言有点令人惊讶).net 运行时除了独立System.Array对象或内置于System.String. 尽管 C# 提供fixed数组类型,但这些类型是使用指针算法以 .net 运行时无法真正理解且无法验证的方式进行操作的。

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

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

于 2013-02-26T16:33:13.727 回答