Compile error: Using strings inside Struct with LayoutKind.Explicit
-
Getting compile (Overwritten area/contains Object field @ offset 21) I want a string that is of length 11 (sender) and a string that is of length 23 (message). Any help is appreciated; I cant see the problem. [StructLayout(LayoutKind.Explicit, Pack = 1, Size = 66, CharSet = CharSet.Ansi)] public struct chat { [FieldOffset(0)] public int packetType; //4 [FieldOffset(4)] public int packetNumber; //4 [FieldOffset(8)] public int packetSource; //4 [FieldOffset(12)] public int packetDestination; //4 [FieldOffset(16)] public short packetPort; // 2 [FieldOffset(18)] public ushort packetInfoEnd; // 2 [FieldOffset(20)] public byte dataId; // 1 [FieldOffset(21)] public string dataSender; // 11 [FieldOffset(32)] public byte dataPadOne; // 1 [FieldOffset(33)] public string dataMessage; // 23 [FieldOffset(56)] public short dataPart; // 2 [FieldOffset(58)] public int dataEndCodeOne; // 4 [FieldOffset(62)] public int dataEndCodeTwo; // 4 public chat(int dst, short port, string sender, string message) { packetType = 1192961; packetNumber = 0; packetSource = 0; packetDestination = dst; packetPort = IPAddress.HostToNetworkOrder(port); packetInfoEnd = 43521; dataId = 10; dataSender = sender; dataPadOne = 0; dataMessage = message; dataPart = 206; dataEndCodeOne = 10209786; dataEndCodeTwo = 6658; } }
-
Getting compile (Overwritten area/contains Object field @ offset 21) I want a string that is of length 11 (sender) and a string that is of length 23 (message). Any help is appreciated; I cant see the problem. [StructLayout(LayoutKind.Explicit, Pack = 1, Size = 66, CharSet = CharSet.Ansi)] public struct chat { [FieldOffset(0)] public int packetType; //4 [FieldOffset(4)] public int packetNumber; //4 [FieldOffset(8)] public int packetSource; //4 [FieldOffset(12)] public int packetDestination; //4 [FieldOffset(16)] public short packetPort; // 2 [FieldOffset(18)] public ushort packetInfoEnd; // 2 [FieldOffset(20)] public byte dataId; // 1 [FieldOffset(21)] public string dataSender; // 11 [FieldOffset(32)] public byte dataPadOne; // 1 [FieldOffset(33)] public string dataMessage; // 23 [FieldOffset(56)] public short dataPart; // 2 [FieldOffset(58)] public int dataEndCodeOne; // 4 [FieldOffset(62)] public int dataEndCodeTwo; // 4 public chat(int dst, short port, string sender, string message) { packetType = 1192961; packetNumber = 0; packetSource = 0; packetDestination = dst; packetPort = IPAddress.HostToNetworkOrder(port); packetInfoEnd = 43521; dataId = 10; dataSender = sender; dataPadOne = 0; dataMessage = message; dataPart = 206; dataEndCodeOne = 10209786; dataEndCodeTwo = 6658; } }
Hi, in .NET a string is a reference type, so a struct (or anything else) containing a string is actually containing a reference (similar to a pointer), which must and will be "naturally aligned", that is at an offset which is a multiple of 4 or 8. If you must have the content of an array or even a string embedded inside the struct, you can try this:
[MarshalAs(UnmanagedType.ByValTStr,SizeConst=32)]
public string dmDeviceName;
[MarshalAs(UnmanagedType.ByValArray, SizeConst=15)]
public int[] data;that effectively turns reference types into value types as far as storage allocation goes. :)
Luc Pattyn [Forum Guidelines] [My Articles]
- before you ask a question here, search CodeProject, then Google - the quality and detail of your question reflects on the effectiveness of the help you are likely to get - use the code block button (PRE tags) to preserve formatting when showing multi-line code snippets
modified on Sunday, June 12, 2011 8:29 AM
-
Hi, in .NET a string is a reference type, so a struct (or anything else) containing a string is actually containing a reference (similar to a pointer), which must and will be "naturally aligned", that is at an offset which is a multiple of 4 or 8. If you must have the content of an array or even a string embedded inside the struct, you can try this:
[MarshalAs(UnmanagedType.ByValTStr,SizeConst=32)]
public string dmDeviceName;
[MarshalAs(UnmanagedType.ByValArray, SizeConst=15)]
public int[] data;that effectively turns reference types into value types as far as storage allocation goes. :)
Luc Pattyn [Forum Guidelines] [My Articles]
- before you ask a question here, search CodeProject, then Google - the quality and detail of your question reflects on the effectiveness of the help you are likely to get - use the code block button (PRE tags) to preserve formatting when showing multi-line code snippets
modified on Sunday, June 12, 2011 8:29 AM
Thank you! It worked perfectly! Very much appreciated
-
Hi, in .NET a string is a reference type, so a struct (or anything else) containing a string is actually containing a reference (similar to a pointer), which must and will be "naturally aligned", that is at an offset which is a multiple of 4 or 8. If you must have the content of an array or even a string embedded inside the struct, you can try this:
[MarshalAs(UnmanagedType.ByValTStr,SizeConst=32)]
public string dmDeviceName;
[MarshalAs(UnmanagedType.ByValArray, SizeConst=15)]
public int[] data;that effectively turns reference types into value types as far as storage allocation goes. :)
Luc Pattyn [Forum Guidelines] [My Articles]
- before you ask a question here, search CodeProject, then Google - the quality and detail of your question reflects on the effectiveness of the help you are likely to get - use the code block button (PRE tags) to preserve formatting when showing multi-line code snippets
modified on Sunday, June 12, 2011 8:29 AM
Just a note for anyone else who comes across this issue and sees this thread: The solution provided by Luc does NOT WORK with LayoutKind.Explicit, it only works with LayoutKind.Sequential, and with the FieldOffset()'s removed (obviously). This is the compiling + working code:
[StructLayout(LayoutKind.Sequential, Pack = 1, Size = 66, CharSet = CharSet.Ansi)]
public struct chatOne
{public int packetType; //4 public int packetNumber; //4 public int packetSource; //4 public int packetDestination; //4 public short packetPort; // 2 public ushort packetInfoEnd; // 2 public byte dataId; // 1 \[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 11)\] public string dataSender; // 11 public byte dataPadOne; // 1 \[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 23)\] public string dataMessage; // 23 public short dataPart; // 2 public int dataEndCodeOne; // 4 public int dataEndCodeTwo; // 4 public chatOne(int dst, short port, string sender, string message) { packetType = 1192961; packetNumber = 0; packetSource = 0; packetDestination = dst; packetPort = IPAddress.HostToNetworkOrder(port); packetInfoEnd = 43521; dataId = 10; dataSender = sender; dataPadOne = 0; dataMessage = message; dataPart = 206; dataEndCodeOne = 10209786; dataEndCodeTwo = 6658; } }