如何在C#中创建此结构?

时间:2012-11-28 05:45:34

标签: c# struct pinvoke unions

我正在尝试在这篇msdn文章中创建以下结构。我正在尝试学习整个FieldOffset,但不知道从哪里开始。

我基本上做了类似的事。

[StructLayout(LayoutKind.Explicit, Size=12)]
public struct DHCP_OPTION_DATA_ELEMENT {
    [FieldOffset(0)]
    public DHCP_OPTION_DATA_TYPE OptionType;
    [FieldOffset(4)]
    public byte ByteOption;
    [FieldOffset(4)]
    public uint WordOption;
    [FieldOffset(4)]
    public UInt32 DWordOption;
    [FieldOffset(4)]
    public UInt32 DWordDWordOption;
    [FieldOffset(4)]
    public uint IpAddressOption;
    [FieldOffset(4)]
    public IntPtr StringDataOption;
    [FieldOffset(4)]
    public DHCP_BINARY_DATA BinaryDataOption;
    [FieldOffset(4)]
    public DHCP_BINARY_DATA EncapsulatedDataOption;
    [FieldOffset(4)]
    public string Ipv6AddressDataOption;
}

然而,它在我面前咆哮说明了以下异常。

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

3 个答案:

答案 0 :(得分:2)

将其视为IntPtr,而不是字符串。

但是,在使用IntPtr时,请确保自己完成清理,因为现在您将使用非托管内存,因此GC不会帮助您,导致每个内存泄漏你传递这个结构的时间。

你很可能想要使用Marshal.PtrToStringUni函数,正如shf301在另一个答案中建议的那样。

答案 1 :(得分:1)

错误

  

它包含偏移4处的对象字段,该字段未正确对齐或   由非对象字段重叠。

是由于非对象(blittable)类型(例如Uint32)与对象类型(非blittable)重叠。编组人无法处理。 marhshaler不知道联合的哪个字段是有效的(因为它不知道如何解码OptionType所以它不知道它是否应该编组字符串值或整数值。试图编组一个字符串的整数值会导致崩溃(因为整数值不会指向有效的字符串),因此编组器抛出异常而不是让您崩溃。

因此,您必须手动编组字符串,方法是将其定义为IntPtr并使用Marshal.PtrToStringUni()Marshal.PtrToStringAnsi()

您也可能遇到与DHCP_BINARY_DATA相同的问题。

答案 2 :(得分:0)

您有以下代码:

[FieldOffset(4)]
public string Ipv6AddressDataOption;

String是引用类型(对象),其他字段是值类型(非对象)。因此,您必须更改Ipv6AddressDataOption的偏移量。