代码之家  ›  专栏  ›  技术社区  ›  Bitterblue

具有另一结构的固定大小阵列的结构

  •  2
  • Bitterblue  · 技术社区  · 13 年前

    如何用另一个结构的固定大小数组来声明C#中的一个结构?我需要 this 声明使其工作。或者,如果我想要创建位图信息(-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 如果我分配256大小的RGBQUAD数组,则将大小恒定地封送为44字节事件。

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

    2 回复  |  直到 13 年前
        1
  •  4
  •   supercat    13 年前

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

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

    如果您不需要使用 safe 代码(考虑到您正在与可能不受信任的托管代码进行互操作,“安全”代码可能不是一个考虑因素)我建议您定义 RGBQUAD 使用显式布局,重叠 int 使用您的其他数据,然后让您的其他结构包括 fixed int[whateverSize]; 以保持RGB数据。其索引访问器应该能够转换 整数 rgb四边形 只需读取/写入其“int”成员即可相当有效。

        2
  •  3
  •   arx    13 年前

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

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

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

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

    在C#中如何处理这一问题完全取决于您使用 BITMAPINFO 结构

    使现代化

    我刚刚看到你的另一个问题。你正在通过 位图信息 SetDIBits 你的颜色表总是有256个条目。因此,在 BITMAPINFO.bmiColors 设置 SizeConst 至256。