StructLayout特性允许我们控制Structure语句块的元素在内存中的排列方式,以及当这些元素被传递给外部DLL时,运行库排列这些元素的方式。
1.Sequential,顺序布局
这样在内存里是先排a,再排b,也就是如果能取到a的地址和b的地址,则相差一个int类型的长度,4字节。因为默认的内存排列就是Sequential,也就是按成员的先后顺序排列。
2.Explicit,精确布局
需要用FieldOffset()设置每个成员的位置
StructLayout特性支持三种附加字段:CharSet、Pack、Size。
- CharSet定义在结构体中的字符串成员在结构被传给DLL时的排列方式。可以是Unicode、Ansi或Auto。
- Pack定义了结构体的封装大小。可以是1、2、4、8、16、32、64、128或特殊值0。特殊值0表示当前操作平台默认的压缩大小。比如,上面的顺序布局中,就设置结构大小为1。
- Size指示类或结构的绝对大小,此字段必须为等于或大于总大小。
3.一般在实际开发中,我们的属性列表都是有很多条组成的,所以需要在结构体中嵌入数组。此处,用的上文的Prop结构体作为数组的类型。
这里用到了用到MashalAs特性,它用于描述字段、方法或参数的封送处理格式。用它作为参数前缀并指定目标需要的数据类型。
嵌入结构体的数组可以通过使用UnmanagedType.ByValArray并用MarshalAsAttribute.SizeConst指定数组大小的 MarshalAs 属性来封送。包含字符串的数组可以使用UnmanagedType.ByValTStr 来指定字符串。
定义了结构,如何使用呢?需要使用Marshal.PtrTostructure将数据从非托管内存块封送到新分配的指定类型的托管对象。