【问题标题】:C Union in C# Error incorrectly aligned or overlapped by a non-object fieldC# 错误中的 C Union 错误对齐或被非对象字段重叠
【发布时间】:2013-06-07 18:29:50
【问题描述】:

我正在开发 C# WPF 应用程序并尝试使用非托管 dll(无权访问源代码)。我需要的结构是“NET_DVR_IPPARACFG_V40”,其中包含一堆其他结构/联合。以下是文档提供给我们的信息:

struct{
  DWORD                   dwSize;
  DWORD                   dwGroupNum;
  DWORD                   dwAChanNum;
  DWORD                   dwDChanNum;
  DWORD                   dwStartDChan;
  BYTE                    byAnalogChanEnable[MAX_CHANNUM_V30];
  NET_DVR_IPDEVINFO_V31   struIPDevInfo[MAX_IP_DEVICE_V40];
  NET_DVR_STREAM_MODE     struStreamMode[MAX_CHANNUM_V30];
  BYTE                    byRes2[20];
}NET_DVR_IPPARACFG_V40

struct{
  BYTE               byEnable;
  BYTE               byProType;
  BYTE               byEnableQuickAdd;
  BYTE               byRes1;
  BYTE               sUserName[NAME_LEN];
  BYTE               sPassword[PASSWD_LEN];
  BYTE               byDomain[MAX_DOMAIN_NAME];
  NET_DVR_IPADDR     struIP;
  WORD               wDVRPort;
  BYTE               byRes2[34];
}NET_DVR_IPDEVINFO_V31

struct{
  char    sIpV4[16];
  BYTE    sIpV6[128];
}NET_DVR_IPADDR

struct{
  BYTE                      byGetStreamType;
  BYTE                      byRes[3];
  NET_DVR_GET_STREAM_UNION  uGetStream;
}NET_DVR_STREAM_MODE

union{
  NET_DVR_IPCHANINFO          struChanInfo;
  NET_DVR_IPSERVER_STREAM     struIPServerStream;
  NET_DVR_PU_STREAM_CFG       struPUStream;
  NET_DVR_DDNS_STREAM_CFG     struDDNSStream;
  NET_DVR_PU_STREAM_URL       struStreamUrl;
  NET_DVR_HKDDNS_STREAM       struHkDDNSStream;
}NET_DVR_GET_STREAM_UNION

struct{
  BYTE     byEnable;
  BYTE     byIPID;
  BYTE     byChannel;
  BYTE     byIPIDHigh;
  BYTE     byRes[32];
}NET_DVR_IPCHANINFO

struct{
  BYTE               byEnable;
  BYTE               byRes[3];
  NET_DVR_IPADDR     struIPServer;
  WORD               wPort;
  WORD               wDvrNameLen;
  BYTE               byDVRName[NAME_LEN];
  WORD               wDVRSerialLen;
  WORD               byRes1[2];
  BYTE               byDVRSerialNumber[SERIALNO_LEN];
  BYTE               byUserName[NAME_LEN];
  BYTE               byPassWord[PASSWD_LEN];
  BYTE               byChannel;
  BYTE               byRes2[11];
}NET_DVR_IPSERVER_STREAM

struct{
  DWORD                             dwSize;
  NET_DVR_STREAM_MEDIA_SERVER_CFG   struStreamMediaSvrCfg;
  NET_DVR_DEV_CHAN_INFO             struDevChanInfo;
}NET_DVR_PU_STREAM_CFG

struct{
  NET_DVR_IPADDR   struIP;
  WORD             wDVRPort;
  BYTE             byChannel;
  BYTE             byTransProtocol;
  BYTE             byTransMode;
  BYTE             byFactoryType; 
  BYTE             byDeviceType;
  BYTE             byDispChan;
  BYTE             bySubDispChan; 
  BYTE             byRes[3];
  BYTE             byDomain[MAX_DOMAIN_NAME]; 
  BYTE             sUserName[NAME_LEN];
  BYTE             sPassword[PASSWD_LEN];
}NET_DVR_DEV_CHAN_INFO

struct{
  DWORD                             dwSize;
  NET_DVR_STREAM_MEDIA_SERVER_CFG   struStreamMediaSvrCfg;
  NET_DVR_DEV_CHAN_INFO             struDevChanInfo;
}NET_DVR_PU_STREAM_CFG

struct{
  BYTE             byValid;
  BYTE             byRes1[3];
  NET_DVR_IPADDR   struDevIP;
  WORD             wDevPort;
  BYTE             byTransmitType;
  BYTE             byRes2[69];
}NET_DVR_STREAM_MEDIA_SERVER_CFG

struct{
  BYTE               byEnable;
  BYTE               byRes1[3];
  NET_DVR_IPADDR     struStreamServer;
  WORD               wStreamServerPort;
  BYTE               byStreamServerTransmitType;
  BYTE               byRes2;
  NET_DVR_IPADDR     struIPServer;
  WORD               wIPServerPort;
  BYTE               byRes3[2];
  BYTE               sDVRName[NAME_LEN];
  WORD               wDVRNameLen;
  WORD               wDVRSerialLen;
  BYTE               sDVRSerialNumber[SERIALNO_LEN];
  BYTE               sUserName[NAME_LEN];
  BYTE               sPassWord[PASSWD_LEN];
  WORD               wDVRPort;
  BYTE               byRes4[2];
  BYTE               byChannel;
  BYTE               byTransProtocol;
  BYTE               byTransMode;
  BYTE               byFactoryType;
}NET_DVR_DDNS_STREAM_CFG

struct{
  BYTE    byEnable;
  BYTE    strURL[240];
  BYTE    byTransPortocol ;
  WORD    wIPID;
  BYTE    byChannel;
  BYTE    byRes[7];
}NET_DVR_PU_STREAM_URL

struct{
  BYTE    byEnable;
  BYTE    byRes[3];
  BYTE    byDDNSDomain[64];
  WORD    wPort;
  WORD    wAliasLen;
  BYTE    byAlias[NAME_LEN];
  WORD    wDVRSerialLen;
  BYTE    byRes1[2];
  BYTE    byDVRSerialNumber[SERIALNO_LEN];
  BYTE    byUserName[NAME_LEN];
  BYTE    byPassWord[PASSWD_LEN];
  BYTE    byChannel;
  BYTE    byRes2[11];
}NET_DVR_HKDDNS_STREAM

我已经阅读了大量在线文档,但似乎仍然无法正确编组这个“NET_DVR_IPPARACFG_V40”。这是我在 C# 中的内容:

/*[StructLayoutAttribute(LayoutKind.Sequential)]
public struct NET_DVR_IPPARACFG_V40
{
    public uint dwSize;
    public uint dwGroupNum;
    public uint dwAChanNum;
    public uint dwDChanNum;
    public uint dwStartDChan;
    [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = MAX_CHANNUM_V30, ArraySubType = UnmanagedType.I1)]
    public byte[] byAnalogChanEnable;
    [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = MAX_IP_DEVICE_V40, ArraySubType = UnmanagedType.Struct)]
    public NET_DVR_IPDEVINFO_V31[] struIPDevInfo;
    [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = MAX_CHANNUM_V30, ArraySubType = UnmanagedType.Struct)]
    public NET_DVR_STREAM_MODE[] struStreamMode;
    public byte[] byRes2;
}*/
[StructLayoutAttribute(LayoutKind.Sequential, Pack = 1)]
public struct NET_DVR_IPPARACFG_V40
{
    public uint dwSize;
    public uint dwGroupNum;
    public uint dwAChanNum;
    public uint dwDChanNum;
    public uint dwStartDChan;
    unsafe public fixed byte byAnalogChanEnable[MAX_CHANNUM_V30];
    [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = MAX_IP_DEVICE_V40, ArraySubType = UnmanagedType.Struct)]
    public NET_DVR_IPDEVINFO_V31[] struIPDevInfo;
    [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = MAX_CHANNUM_V30, ArraySubType = UnmanagedType.Struct)]
    public NET_DVR_STREAM_MODE[] struStreamMode;
    unsafe public fixed byte byRes2[20];
}

/*[StructLayoutAttribute(LayoutKind.Sequential)]
public struct NET_DVR_IPDEVINFO_V31
{
    public byte byEnable;
    public byte byProType;
    public byte byEnableQuickAdd;
    public byte byRes1;
    [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = NAME_LEN, ArraySubType = UnmanagedType.I1)]
    public byte[] sUserName;
    [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = PASSWD_LEN, ArraySubType = UnmanagedType.I1)]
    public byte[] sPassword;
    [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = MAX_DOMAIN_NAME, ArraySubType = UnmanagedType.I1)]
    public byte[] byDomain;
    public NET_DVR_IPADDR struIP;
    public ushort wDVRPort;
    public byte[] byRes;
}*/
[StructLayoutAttribute(LayoutKind.Sequential, Pack = 1)]
public struct NET_DVR_IPDEVINFO_V31
{
    public byte byEnable;
    public byte byProType;
    public byte byEnableQuickAdd;
    public byte byRes1;
    unsafe public fixed byte sUserName[NAME_LEN];
    unsafe public fixed byte sPassword[PASSWD_LEN];
    unsafe public fixed byte byDomain[MAX_DOMAIN_NAME];
    public NET_DVR_IPADDR struIP;
    public ushort wDVRPort;
    unsafe public fixed byte byRes[34];
}

/*[StructLayoutAttribute(LayoutKind.Sequential)]
public struct NET_DVR_STREAM_MODE
{
    public byte byGetStreamType;
    public byte[] byRes;
    public NET_DVR_GET_STREAM_UNION uGetStream;
}*/
[StructLayoutAttribute(LayoutKind.Sequential, Pack = 1)]
public struct NET_DVR_STREAM_MODE
{
    public byte byGetStreamType;
    unsafe public fixed byte byRes[3];
    public NET_DVR_GET_STREAM_UNION uGetStream;
}

/*[StructLayout(LayoutKind.Explicit, Size = 528)]
public struct NET_DVR_GET_STREAM_UNION
{
    [FieldOffset(0)]
    public NET_DVR_IPCHANINFO struChanInfo;
    [FieldOffset(0)]
    public NET_DVR_IPSERVER_STREAM struIPServerStream;
    [FieldOffset(0)]
    public NET_DVR_PU_STREAM_CFG struPUStream;
    [FieldOffset(0)]
    public NET_DVR_DDNS_STREAM_CFG struDDNSStream;
    [FieldOffset(0)]
    public NET_DVR_PU_STREAM_URL struStreamUrl;
    [FieldOffset(0)]
    public NET_DVR_HKDDNS_STREAM struHkDDNSStream;
}*/
[StructLayout(LayoutKind.Explicit)]
public struct NET_DVR_GET_STREAM_UNION
{
    [FieldOffset(0)]
    public NET_DVR_IPCHANINFO struChanInfo;
    [FieldOffset(0)]
    public NET_DVR_IPSERVER_STREAM struIPServerStream;
    [FieldOffset(0)]
    public NET_DVR_PU_STREAM_CFG struPUStream;
    [FieldOffset(0)]
    public NET_DVR_DDNS_STREAM_CFG struDDNSStream;
    [FieldOffset(0)]
    public NET_DVR_PU_STREAM_URL struStreamUrl;
    [FieldOffset(0)]
    public NET_DVR_HKDDNS_STREAM struHkDDNSStream;
}

/*[StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct NET_DVR_IPADDR
{

    /// char[16]
    [MarshalAsAttribute(UnmanagedType.ByValTStr, SizeConst = 16)]
    public string sIpV4;

    /// BYTE[128]
    [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 128, ArraySubType = UnmanagedType.I1)]
    public byte[] byRes;

    public void Init()
    {
        byRes = new byte[128];
    }
}*/
[StructLayoutAttribute(LayoutKind.Sequential, Pack = 1)]
public struct NET_DVR_IPADDR
{
    [MarshalAsAttribute(UnmanagedType.ByValTStr, SizeConst = 16)]
    public string sIpV4;
    unsafe public fixed byte byRes[128];
}

/*[StructLayoutAttribute(LayoutKind.Sequential)]
public struct NET_DVR_DEV_CHAN_INFO
{
    public NET_DVR_IPADDR struIP;
    public ushort wDVRPort;
    public byte byChannel;
    public byte byTransProtocol;
    public byte byTransMode;
    public byte byFactoryType;
    [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 6, ArraySubType = UnmanagedType.I1)]
    public byte[] byRes;
    [MarshalAsAttribute(UnmanagedType.ByValTStr, SizeConst = MAX_DOMAIN_NAME)]
    public string byDomain;
    [MarshalAsAttribute(UnmanagedType.ByValTStr, SizeConst = NAME_LEN)]
    public string sUserName;
    [MarshalAsAttribute(UnmanagedType.ByValTStr, SizeConst = PASSWD_LEN)]
    public string sPassword;
}*/
[StructLayoutAttribute(LayoutKind.Sequential, Pack = 1)]
public struct NET_DVR_DEV_CHAN_INFO
{
    public NET_DVR_IPADDR struIP;
    public ushort wDVRPort;
    public byte byChannel;
    public byte byTransProtocol;
    public byte byTransMode;
    public byte byFactoryType;
    unsafe public fixed byte byRes[6];
    [MarshalAsAttribute(UnmanagedType.ByValTStr, SizeConst = MAX_DOMAIN_NAME)]
    public string byDomain;
    [MarshalAsAttribute(UnmanagedType.ByValTStr, SizeConst = NAME_LEN)]
    public string sUserName;
    [MarshalAsAttribute(UnmanagedType.ByValTStr, SizeConst = PASSWD_LEN)]
    public string sPassword;
}

/*[StructLayoutAttribute(LayoutKind.Sequential)]
public struct NET_DVR_STREAM_MEDIA_SERVER_CFG
{
    public byte byValid;
    [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 3, ArraySubType = UnmanagedType.I1)]
    public byte[] byRes1;
    public NET_DVR_IPADDR struDevIP;
    public ushort wDevPort;
    public byte byTransmitType;
    [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 69, ArraySubType = UnmanagedType.I1)]
    public byte[] byRes2;
}*/
[StructLayoutAttribute(LayoutKind.Sequential, Pack = 1)]
public struct NET_DVR_STREAM_MEDIA_SERVER_CFG
{
    public byte byValid;
    unsafe public fixed byte byRes1[3];
    public NET_DVR_IPADDR struDevIP;
    public ushort wDevPort;
    public byte byTransmitType;
    unsafe public fixed byte byRes2[69];
}



/*[StructLayoutAttribute(LayoutKind.Sequential)]
public struct NET_DVR_IPCHANINFO
{
    public byte byEnable;
    public byte byIPID;
    public byte byChannel;
    public byte byProType;
    [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 32, ArraySubType = UnmanagedType.I1)]
    public byte[] byRes;
    public void Init()
    {
        byRes = new byte[32];
    }
}*/
[StructLayoutAttribute(LayoutKind.Sequential, Pack = 1)]
public struct NET_DVR_IPCHANINFO
{
    public byte byEnable;
    public byte byIPID;
    public byte byChannel;
    public byte byProType;
    unsafe public fixed byte byRes[32];
}

/*[StructLayoutAttribute(LayoutKind.Sequential)]
public struct NET_DVR_IPSERVER_STREAM
{
    public byte byEnable;
    public byte[] byRes;
    public NET_DVR_IPADDR struIPServer;
    public ushort wPort;
    public ushort wDvrNameLen;
    [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = NAME_LEN, ArraySubType = UnmanagedType.I1)]
    public byte[] byDVRName;
    public ushort wDVRSerialLen;
    public ushort[] byRes1;
    [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = SERIALNO_LEN, ArraySubType = UnmanagedType.I1)]
    public byte[] byDVRSerialNumber;
    [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = NAME_LEN, ArraySubType = UnmanagedType.I1)]
    public byte[] byUserName;
    [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = PASSWD_LEN, ArraySubType = UnmanagedType.I1)]
    public byte[] byPassWord;
    public byte byChannel;
    public byte[] byRes2;
}*/
[StructLayoutAttribute(LayoutKind.Sequential, Pack = 1)]
public struct NET_DVR_IPSERVER_STREAM
{
    public byte byEnable;
    unsafe public fixed byte byRes[3];
    public NET_DVR_IPADDR struIPServer;
    public ushort wPort;
    public ushort wDvrNameLen;
    unsafe public fixed byte byDVRName[NAME_LEN];
    public ushort wDVRSerialLen;
    unsafe public fixed ushort byRes1[2];
    unsafe public fixed byte byDVRSerialNumber[SERIALNO_LEN];
    unsafe public fixed byte byUserName[NAME_LEN];
    unsafe public fixed byte byPassWord[PASSWD_LEN];
    public byte byChannel;
    unsafe public fixed byte byRes2[11];
}

/*[StructLayoutAttribute(LayoutKind.Sequential)]
public struct NET_DVR_PU_STREAM_CFG
{
    public uint dwSize;
    public NET_DVR_STREAM_MEDIA_SERVER_CFG struStreamMediaSvrCfg;
    public NET_DVR_DEV_CHAN_INFO struDevChanInfo;
}*/
[StructLayoutAttribute(LayoutKind.Sequential, Pack = 1)]
public unsafe struct NET_DVR_PU_STREAM_CFG
{
    public uint dwSize;
    public NET_DVR_STREAM_MEDIA_SERVER_CFG struStreamMediaSvrCfg;
    public NET_DVR_DEV_CHAN_INFO struDevChanInfo;
}

/*[StructLayoutAttribute(LayoutKind.Sequential)]
public struct NET_DVR_DDNS_STREAM_CFG
{
    public byte byEnable;
    public byte[] byRes1;
    public NET_DVR_IPADDR struStreamServer;
    public ushort wStreamServerPort;
    public byte byStreamServerTransmitType;
    public byte byRes2;
    public NET_DVR_IPADDR struIPServer;
    public byte wIPServerPort;
    public byte[] byRes3;
    [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = NAME_LEN, ArraySubType = UnmanagedType.I1)]
    public byte[] sDVRName;
    public ushort wDVRNameLen;
    public ushort wDVRSerialLen;
    [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = SERIALNO_LEN, ArraySubType = UnmanagedType.I1)]
    public byte[] sDVRSerialNumber;
    [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = NAME_LEN, ArraySubType = UnmanagedType.I1)]
    public byte[] sUserName;
    [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = PASSWD_LEN, ArraySubType = UnmanagedType.I1)]
    public byte[] sPassWord;
    public ushort wDVRPort;
    public byte[] byRes4;
    public byte byChannel;
    public byte byTransProtocol;
    public byte byTransMode;
    public byte byFactoryType;
}*/
[StructLayoutAttribute(LayoutKind.Sequential, Pack = 1)]
public struct NET_DVR_DDNS_STREAM_CFG
{
    public byte byEnable;
    unsafe public fixed byte byRes1[3];
    public NET_DVR_IPADDR struStreamServer;
    public ushort wStreamServerPort;
    public byte byStreamServerTransmitType;
    public byte byRes2;
    public NET_DVR_IPADDR struIPServer;
    public byte wIPServerPort;
    unsafe public fixed byte byRes3[2];
    unsafe public fixed byte sDVRName[NAME_LEN];
    public ushort wDVRNameLen;
    public ushort wDVRSerialLen;
    unsafe public fixed byte sDVRSerialNumber[SERIALNO_LEN];
    unsafe public fixed byte sUserName[NAME_LEN];
    unsafe public fixed byte sPassWord[PASSWD_LEN];
    public ushort wDVRPort;
    unsafe public fixed byte byRes4[2];
    public byte byChannel;
    public byte byTransProtocol;
    public byte byTransMode;
    public byte byFactoryType;
}

/*[StructLayoutAttribute(LayoutKind.Sequential)]
public struct NET_DVR_PU_STREAM_URL
{
    public byte byEnable;
    public byte[] strURL;
    public byte byTransPortocol;
    public ushort wIPID;
    public byte byChannel;
    public byte[] byRes;
}*/
[StructLayoutAttribute(LayoutKind.Sequential, Pack = 1)]
public struct NET_DVR_PU_STREAM_URL
{
    public byte byEnable;
    unsafe public fixed byte strURL[240];
    public byte byTransPortocol;
    public ushort wIPID;
    public byte byChannel;
    unsafe public fixed byte byRes[7];
}

/*[StructLayoutAttribute(LayoutKind.Sequential)]
public struct NET_DVR_HKDDNS_STREAM
{
    public byte byEnable;
    public byte[] byRes;
    public byte[] byDDNSDomain;
    public ushort wPort;
    public ushort wAliasLen;
    [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = NAME_LEN, ArraySubType = UnmanagedType.I1)]
    public byte[] byAlias;
    public ushort wDVRSerialLen;
    public byte[] byRes1;
    [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = SERIALNO_LEN, ArraySubType = UnmanagedType.I1)]
    public byte[] byDVRSerialNumber;
    [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = NAME_LEN, ArraySubType = UnmanagedType.I1)]
    public byte[] byUserName;
    [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = PASSWD_LEN, ArraySubType = UnmanagedType.I1)]
    public byte[] byPassWord;
    public byte byChannel;
    public byte[] byRes2;
}*/
[StructLayoutAttribute(LayoutKind.Sequential, Pack = 1)]
public struct NET_DVR_HKDDNS_STREAM
{
    public byte byEnable;
    unsafe public fixed byte byRes[3];
    unsafe public fixed byte byDDNSDomain[64];
    public ushort wPort;
    public ushort wAliasLen;
    unsafe public fixed byte byAlias[NAME_LEN];
    public ushort wDVRSerialLen;
    unsafe public fixed byte byRes1[2];
    unsafe public fixed byte byDVRSerialNumber[SERIALNO_LEN];
    unsafe public fixed byte byUserName[NAME_LEN];
    unsafe public fixed byte byPassWord[PASSWD_LEN];
    public byte byChannel;
    unsafe public fixed byte byRes2[11];
}

它可以编译,但是当我使用此结构进行调用时,我收到错误“无法加载类型,因为它包含偏移量 0 处的对象字段,该对象字段未正确对齐或被非对象字段重叠。”联合中的结构也都有不同的大小,我不确定这是否是一个问题,但认为它值得注意。制造商实际上给了我上面的 C# 结构,但我认为他们没有真正测试过它,因为它不起作用。这是我第一次与工会打交道,所以我不确定如何处理。我的知识范围来自过去几周的研究。

如果有人能提供一些见解,我将不胜感激。

【问题讨论】:

  • 由于 STRUCT_B 包含单字节 (byA) 和 3 字节数组 (byB) 似乎应该按字节对齐:[StructLayoutAttribute(LayoutKind.Sequential, Pack = 1)] public struct STRUCT_B跨度>
  • 能否提供 STRUCT_A..STRUCT_H 来重现错误?
  • 好的,这是一个公共 SDK,所以我没有花时间重命名所有内容,而是更改了以前的内容。我要创建的主要结构是'NET_DVR_IPPARACFG_V40'。列出的所有其他结构都以某种方式与该结构相关。我会在一分钟内更新我在 C# 中的内容。
  • 我创建了一个小的 c++ 应用程序来直接从 DLL 获取所有结构的大小,并将其与我在 C# 中获得的大小进行比较,它们都相等(除了 'NET_DVR_GET_STREAM_UNION'当我在 C# 中检查大小时会出错)。但是联合中结构的大小相等。所以我想这只是一个对齐问题?我不知道。如果有人可以为我提供更多帮助,我将不胜感激

标签: c# data-structures struct marshalling unions


【解决方案1】:

编组的时候要注意两点:

  1. 对齐方式(1、2、4 字节)

  2. 尺寸和偏移量

    每当我们遇到像 BYTE、WORD、BYTE[69] 这样不是 4 字节(32 位)的值时 对齐我们应该明确地对齐:

[StructLayout(LayoutKind.Sequential, Pack = 1)] // <- Pack = 1, byte border alignment 

每当我们有像 BYTE[69] 这样的数组时,我们都应该告知 .Net 数组的大小, 像这样:

fixed byte byRes2[69]; // <- do not move (re-align) 69 bytes! And address them as array

最后,我们可以通过 sizeof() 函数检查我们是否做得很好。 例如,让我们编组给定结构之一

  struct{
    BYTE             byValid;
    BYTE             byRes1[3];
    NET_DVR_IPADDR   struDevIP;
    WORD             wDevPort;
    BYTE             byTransmitType;
    BYTE             byRes2[69];
  }NET_DVR_STREAM_MEDIA_SERVER_CFG

我们可以看到,它具有非平凡的对齐方式(因为 structire 包含单个字节、单词、 不是 4*Byte 值的数组)以及数组。所以 C# 包装将是

  [StructLayout(LayoutKind.Sequential, Pack = 1)]
  public unsafe struct NET_DVR_STREAM_MEDIA_SERVER_CFG {
    byte       byValid;
    fixed byte byRes1[3];
    int        struDevIP; // <- I suggest IP v4 using here (Int32)
    UInt16     wDevPort;
    byte       byTransmitType;
    fixed byte byRes2[69];
  }

是时候检查一下了:初始结构体大小使用1 + 3 + 4 + 2 + 1 + 69 = 80字节, 实际大小是

sizeof(NET_DVR_STREAM_MEDIA_SERVER_CFG) 

返回 80。

【讨论】:

  • 感谢德米特里的信息。从那以后。这个周末我会再玩一些,看看我想出了什么。
  • Dmitry,我用我的“尝试”更新了第二个代码块中的代码,但是当我检查“NET_DVR_GET_STREAM_UNION”的大小时,我仍然收到相同的错误消息。我应该对结构的字符串和数组做一些不同的事情吗?
【解决方案2】:

在其他人的帮助下,我们终于搞定了结构。以下是处理联合的 2 个结构:

[StructLayoutAttribute(LayoutKind.Sequential)]
public struct NET_DVR_GET_STREAM_UNION
{
    [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 492, ArraySubType = UnmanagedType.I1)]
    public byte[] byUnion;
    public void Init()
    {
        byUnion = new byte[492];
    }
}

[StructLayoutAttribute(LayoutKind.Sequential)]
public struct NET_DVR_STREAM_MODE
{  
    public byte  byGetStreamType;
    [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 3, ArraySubType = UnmanagedType.I1)]
    public byte[]  byRes;
    public NET_DVR_GET_STREAM_UNION uGetStream;
    public void Init()
    {
        byGetStreamType = 0;
        byRes = new byte[3];
        uGetStream.Init();
    }
}

基本上,我们只是为匿名数据的联合使用一个字节[]。然后当我们进行调用时,我们可以使用 NET_DVR_STREAM_MODE 中的 byGetStreamType 作为开关,将 byte[] 解析/转换为适当的类型。

感谢所有提供帮助的人的意见。

【讨论】:

    【解决方案3】:

    我不确定,但尺寸可能不对。如果 528 基于 32 位指针,而您使用 64 位指针进行编译,则大小会很小。 STRUCT_X struX 之一可能会“溢出”结构。

    什么时候抛出异常?就在程序启动时或您第一次尝试创建union_as/main_structs 之一时?

    【讨论】:

    • 我实际上是针对 x86 构建的。我什至还没有尝试x64。尝试创建结构时出现错误。它会编译并运行,直到我单击启动要创建的结构的按钮。
    • 是否需要尺寸?如果您删除大小并让编译器处理会发生什么?
    猜你喜欢
    • 2010-11-14
    • 2020-10-05
    • 1970-01-01
    • 1970-01-01
    • 2012-05-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多