如何在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.ByValArray
和SizeConst = 1
对于保持BITMAPINFO编组大小始终为44字节事件非常重要256个大小的RGBQUAD数组。
编辑2:但是SizeConst不能小于实际的数组大小,否则非托管代码可能会使应用程序崩溃。
答案 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.bmiColors
将SizeConst
设置为256。
答案 1 :(得分:3)
不幸的是(和IMHO有点令人惊讶地认为.net的设计目标之一是促进与COM的互操作).net运行时不了解除独立System.Array
对象或角色之外的任何类型的数组内置于System.String
的数组。虽然C#提供fixed
数组类型,但是这些数组类型是使用指针算法操作的,其方式是.net运行时不能理解且无法验证。
通过使用元素a0
,a1
,a2
等定义结构并编写使用的索引属性,可以创建行为类似于固定大小数组的内容。一个switch语句或其他这样的构造来访问它的元素,但是这样的构造可能比正常的数组执行得慢得多。
如果您不需要使用safe
代码(并且鉴于您可能与可能不受信任的托管代码进行互操作,“安全”代码可能不是一个考虑因素)我建议您使用显式布局定义RGBQUAD
,将int
与其他数据重叠,然后让其他结构包含fixed int[whateverSize];
来保存RGB数据。它的索引访问器应该能够通过读/写“int”成员来有效地将int
转换为RGBQUAD
。