c# - 将 C union 映射到 C# 结构

标签 c# c interop pinvoke

我正在尝试将 C 结构映射到 C# 以在包装类中使用它,但一直在结构上遇到 TypeLoadException,因为它:

contains an object field at offset 2 that is incorrectly aligned or overlapped by a non-object field.

这里是相关的C代码:

#pragma pack(2)

tyedef unsigned char SPECIAL_ID[16];

typedef struct _idType
{
  unsigned char f;
  unsigned char t;
  union
  {
    unsigned short i_legacy;
    SPECIAL_ID i;
  }
} IDTYPE;  

这是对 C# 结构的最新尝试:

[StructLayout(LayoutKind.Explicit, Pack=2)]
public struct IDTYPE
{
  [FieldOffset(0)]
  public System.Byte f;
  [FieldOffset(1)]
  public System.Byte t;
  [FieldOffset(2)]
  public ushort i_legacy;
  [FieldOffset(2)]
  [MarshalAs(UnmanagedType.ByValTStr, SizeConst=16)]
  public StringBuilder i;
};  

我试过使用和不使用 Pack=2。我已经尝试将 union 移出到具有显式布局和字段偏移量 0 的单独结构,然后在 IDTYPE 的布局顺序结构中使用该结构。我不太确定哪里出错了?

最佳答案

最好为 union 使用一个类型,然后将其与包含的结构聚合。这让框架可以布置类型并计算偏移量,除了将所有成员放置在偏移量为零的 union 之外。

union 中的字节数组使事情变得更加复杂。这里的一种选择是使用固定缓冲区。

[StructLayout(LayoutKind.Explicit)]
public unsafe struct IDTYPE_UNION
{
    [FieldOffset(0)]
    public ushort i_legacy;
    [FieldOffset(0)]
    public fixed byte i[16];
}; 

像这样把它放在包含的结构中:

[StructLayout(LayoutKind.Sequential, Pack=2)]
public struct IDTYPE
{
    public byte f;
    public byte t;
    public IDTYPE_UNION union;
};  

另一种选择是简单地省略 i_legacy 成员,如果您确实需要读取该数据,请从字节数组中读取:

[StructLayout(LayoutKind.Sequential, Pack=2)]
public struct IDTYPE
{
    public byte f;
    public byte t;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst=16)]
    public byte[] i;

    ushort i_legacy
    {
        get
        {
            return (ushort)((ushort)i[0] << 8 | (ushort)i[1]);
        }
    }
};  

此选项确实允许您避免使用不安全的代码。

关于c# - 将 C union 映射到 C# 结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35655327/

相关文章:

c# - 异步/等待有/没有等待(即发即弃)

c# - .NET 程序最快的 IPC 方法是什么?

c# Mysql转Datagridview重复值

C 中的连接字符串模式

c - 向 Minix 添加打印父进程 ID 系统调用

c# - 使用 wcf Restful 服务通过 WebRequest 的原始正文发送和接收数据?

c - 如何使用Wifi udp套接字编程控制鼠标指针

.net - C++/CLI 自动包装器生成器

scala - 在 JRuby 中访问 Scala 数据结构

sql-server - Service Broker 和 WCF 互操作性