在 c# 中使用 ifdef 和联合的 Marshall 结构

Posted

技术标签:

【中文标题】在 c# 中使用 ifdef 和联合的 Marshall 结构【英文标题】:Marshall Structs with ifdef's and unions in c# 【发布时间】:2013-12-06 13:03:53 【问题描述】:

我在 C 中有以下非托管代码

typedef struct          
PNIO_UINT16    AlarmSpecifier;
PNIO_UINT32    ModIdent;              
PNIO_UINT16    UserAlarmDataLen;    

#ifdef PNIO_ALARM_OLD_STRUC
    PNIO_UINT8     UserAlarmData[PNIO_MAX_ALARM_DATA_LEN]; 
#else
    union 
            PNIO_ALARM_DATA_MAINTENANCE_DIAGNOSIS m_diag; /* Another struct of size 20bytes */
            PNIO_UINT8     UserAlarmData[PNIO_MAX_ALARM_DATA_LEN]; /* Byte array, PNIO_MAX_ALARM_DATA_LEN=1472 */
           UAData;
#endif

 ATTR_PACKED PNIO_ALARM_INFO;

这是我的托管转换,我能够正确推断联合的大小和布局,但我不知道如何处理从 c 代码到 c# 的 ifdef 条件

[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct PNIO_ALARM_INFO

    [FieldOffset(0)]
    public ushort AlarmSpecifier;

    [FieldOffset(2)]
    public uint ModIdent;

    [FieldOffset(6)]
    public ushort UserAlarmDataLen;

    // ifdef condition is true use this field
    //[FieldOffset(8)]
    //[MarshalAs(UnmanagedType.ByValArray, SizeConst = 1472)]
    //public byte[] UserAlarmData;

    // ifdef condition false use following fields
    [FieldOffset(8)]
    public PNIO_ALARM_DATA_MAINTENANCE_DIAGNOSIS m_diag;

    [FieldOffset(28)]
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1472)]
    public byte[] UserAlarmData;

谁能告诉我如何处理 if 条件和联合?

【问题讨论】:

#ifdef in C#的可能重复 @BlackBear 我的要求是不要定义“条件编译符号”。另一方面,“条件属性”听起来很有希望。你能告诉我如何在条件属性中使用“静态只读布尔”字段吗?因为我试过了,而且只有在结构内定义一个 bool 字段时才有可能。而且我不想在我的结构中定义一个 bool 字段。 【参考方案1】:

编译后,C 和 C# 中的结构是静态的,在这方面没有区别。 #ifdef 的工作方式也几乎相同,这里也没有区别。

这里唯一要意识到的是,根据 PNIO_ALARM_OLD_STRUC 的值,编译可以产生两个不同的结构。您需要以相同的方式编译您的 C 和 C# 代码,以便它们产生相同的结构定义。

如果您想用一个 C# 版本处理两个 C 版本,您需要定义两个不同的 C# 结构,以便它们都出现在一个编译单元中。然后你需要弄清楚什么时候使用哪个结构。

【讨论】:

以上是关于在 c# 中使用 ifdef 和联合的 Marshall 结构的主要内容,如果未能解决你的问题,请参考以下文章

在 C# 中使用非原始类型重新创建 C++ 联合类型时出现对齐错误

C# 联合结构编组

如何通过 Visual Studio COM 包装器(或其他方式)在 C# 中使用 C++ 属性联合

与 C# 中的数组缓冲区联合

为啥要在 .c 文件中避免使用 #ifdef?

C#中的可区分联合