【问题标题】:How to correctly calculate struct size using Marshal.SizeOf() in C#?如何在 C# 中使用 Marshal.SizeOf() 正确计算结构大小?
【发布时间】:2021-08-08 12:24:24
【问题描述】:

我正在用这个敲我的头。 我有一个 C# 结构:

    [StructLayout(LayoutKind.Sequential)]
    public struct Enroll
    {
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 101)]
        public char[] Name;
        public UInt16 Port;
        public byte Num;
        public byte Max;
        public UInt64 Version;
        public byte TS;
        public byte Avg;
        public byte Flags;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
        public char[] Tag;
    }

总共 132 个字节。 不过

S.Enroll X = new();
int size = Marshal.SizeOf(X);

计算 144 个字节,因此无法成功将字节映射到结构。

Sender 是一个 C++ 应用程序,其结构声明如下:

struct Enroll
{
public:
    char Name[101] = { 0 };
    uint16 Port = 0;
    uint8 Num = 0;
    uint8 Max = 0;
    uint64 Version = 0;
    uint8 TS = 0;
    uint8 Avg = 0;
    DevFlags Flags = DevFlags ::None;
    char Tag[16] = { 0 };
};

这导致我可以一个一个读取实际的 132 个字节。

我错过了什么?

谢谢

【问题讨论】:

  • 你缺少Pack=1,即:[StructLayout(LayoutKind.Sequential, Pack=1)]
  • 谢谢,现在可以了。所以,供以后参考; Pack=1 究竟做了什么?
  • msdn
  • @MickyD OP 明确表示这是针对 C++ 互操作的;像 protobuf 这样的东西在这里是不必要的间接(虽然如果是我,我可能会考虑“固定缓冲区”而不是那些 char[]
  • @TomislavPlečko 点击我上面评论中的链接。它会将您带到 Pack 的文档。

标签: c# c++ marshalling


【解决方案1】:

正如 Matthew Watson 建议的那样,Pack=1 解决了我的问题。 Link Sinatr 解释说:

Pack 字段控制内存中类型字段的对齐方式。它 影响 LayoutKind.Sequential。默认值为0,表示 当前平台的默认打包大小。包的价值 必须是 0、1、2、4、8、16、32、64 或 128:

类型实例的字段通过以下方式对齐 规则:

类型的对齐方式是其最大元素的大小(1,2,4, 8 等字节)或指定的打包大小,以较小者为准。

每个字段必须与其自己大小的字段对齐(1、2、4、8 等, 字节)或类型的对齐方式,以较小者为准。因为 该类型的默认对齐方式是其最大元素的大小, 大于或等于所有其他字段长度,这 通常意味着字段按其大小对齐。例如,即使 如果类型中的最大字段是 64 位(8 字节)整数或 Pack 字段设置为 8,字节字段对齐 1 字节边界,Int16 字段对齐 2 字节边界,Int32 字段对齐 4 字节 边界。

在字段之间添加填充以满足对齐要求。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-10-04
    • 2019-05-08
    • 1970-01-01
    • 2011-02-09
    • 2015-06-03
    • 1970-01-01
    • 2017-04-26
    • 2022-06-23
    相关资源
    最近更新 更多