简体   繁体   中英

How can I create this struct in C#?

I am trying to create the following struct in this msdn article. I am trying to learn the whole FieldOffset but have no clue where to start.

I basically did something like this.

[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;
}

However, it barked at me stating the following exception.

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

Treat it as an IntPtr, instead of a string.

However, when using an IntPtr, be darn sure you take care of cleaning up after yourself, because you will now be working with unmanaged memory and thus the GC won't be helping you out, leading to a nice memory leak each time you pass this struct around.

You're going to want to be using the Marshal.PtrToStringUni function, most likely, as suggested by shf301 in another answer.

The error

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

Is due to overlapping a non-object ( blittable ) type (eg Uint32 ) with an object type (non-blittable). The marshaler cannot handle that. The marhshaler doesn't know which field of the union is valid (since it doesn't know how to decode OptionType so it doesn't know if it should marshal a string value or an integer value. Trying to marshal an integer value to a string would lead to a crash (since an integer value won't point to a valid string), so the marshaller throws the exception instead of allowing you to crash.

So you have to marshal the strings manually by defining them as IntPtr 's and using Marshal.PtrToStringUni() or Marshal.PtrToStringAnsi() .

You may have the same issue with DHCP_BINARY_DATA as well.

You have this code:

[FieldOffset(4)]
public string Ipv6AddressDataOption;

String is reference type (object), and other fields are value type (non-object). So you have to change the Offset for the Ipv6AddressDataOption .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM