处理FieldOffsets C#C ++

时间:2019-07-12 16:47:34

标签: c# marshalling

我想用c#整理以下c结构。

struct ConnectionMessage
{
    static const size_t MESSAGE_MAX_PATH = 260;

    uint32_t version;
    uint64_t pid;
    char machineName[32];
    char executablePath[MESSAGE_MAX_PATH];
};

struct TextMessage
{
    static const size_t TEXT_SIZE = 256;

    uint64_t timestamp;
    uint32_t severity;
    char module[32];
    char channel[32];
    char message[TEXT_SIZE];
};


struct RawLogMessage
{
    uint32_t type;
    union
    {
        ConnectionMessage connection;
        TextMessage text;
    };
};

在将C#程序集更改为x64之前,我过去使用的结构都可以正常工作。

这些是结构:

[StructLayout(LayoutKind.Explicit, Pack = 1)]
public struct TextMessage
{
    [FieldOffset(0), MarshalAs(UnmanagedType.U8)]
    public UInt64 Timestamp;
    [FieldOffset(8), MarshalAs(UnmanagedType.U4)]
    public LogSeverity Severity;
    [FieldOffset(12), MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
    public string Module;
    [FieldOffset(44), MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
    public string Channel;
    [FieldOffset(76), MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
    public string Message;

    public override string ToString()
    {
        return String.Format("{0} {1} {2} {3} {4}", this.Timestamp, this.Severity, this.Module, this.Channel, this.Message);
    }
}

[StructLayout(LayoutKind.Explicit, Pack = 1)]
public struct ConnectionMessage
{
    [FieldOffset(0)]
    public UInt32 Version;
    [FieldOffset(8)]
    public UInt32 Pid;

    public override string ToString()
    {
        return String.Format("{0} {1}", this.Version, this.Pid);
    }
}


[StructLayout(LayoutKind.Explicit, Pack = 0)]
public struct RawLogMessage
{
    [FieldOffset(0), MarshalAs(UnmanagedType.U4)]
    public MessageType Type;
    [FieldOffset(8)]
    public TextMessage TextMessage;
    [FieldOffset(8)]
    public ConnectionMessage ConnectionMessage;
}

处理该问题的正确方法是什么?将C#随意更改为x64后,它不再起作用的原因是什么?感谢您的提示/帮助。

1 个答案:

答案 0 :(得分:1)

为澄清起见,您最近也开始将C库也编译为64位吗?那可能已经改变了结构上的默认包装,但是可能没有改变。您是否在C代码中手动指定了对齐边界?您需要先澄清这一事实。 C struct包装现在是8个字节还是4个字节?还是设置得紧凑,字节对齐?

在ConnectionMessage :: Pid上字段偏移为8似乎暗示您认为C字段现在是8字节对齐的,因为它上方的字段显然只有4字节宽。而且,如果您是8字节对齐的,则不能有12或44的偏移量,依此类推。如果是字节对齐或4字节对齐的,则将Pid偏移为8字节显然是错误的。关于Text / ConnectionMessage也是如此。