Skip to main content
replaced http://stackoverflow.com/ with https://stackoverflow.com/
Source Link
URL Rewriter Bot
URL Rewriter Bot

Consider the following struct to be sent over TCP to an unmanaged dll

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] public struct FooMessage { [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 42)] public string foo; //More fields... } 

Using the following function (credit to CheesoCheeso):

public byte[] RawSerialize( T item ) { int rawSize = Marshal.SizeOf( typeof(T) ); IntPtr buffer = Marshal.AllocHGlobal( rawSize ); Marshal.StructureToPtr( item, buffer, false ); byte[] rawData = new byte[ rawSize ]; Marshal.Copy( buffer, rawData, 0, rawSize ); Marshal.FreeHGlobal( buffer ); return rawData; } 

Problem: The marshaller assumes foo is a null terminated string, whereas the unmanaged dll does not - and actually uses the last char (which always comes out null from the marshaller).

Any ideas ?

Clarification: I can't just change the SizeConst to 43, because I need to maintain the total size of the message, as well as the position of the next fields in the struct (according to an existing ICD)

Consider the following struct to be sent over TCP to an unmanaged dll

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] public struct FooMessage { [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 42)] public string foo; //More fields... } 

Using the following function (credit to Cheeso):

public byte[] RawSerialize( T item ) { int rawSize = Marshal.SizeOf( typeof(T) ); IntPtr buffer = Marshal.AllocHGlobal( rawSize ); Marshal.StructureToPtr( item, buffer, false ); byte[] rawData = new byte[ rawSize ]; Marshal.Copy( buffer, rawData, 0, rawSize ); Marshal.FreeHGlobal( buffer ); return rawData; } 

Problem: The marshaller assumes foo is a null terminated string, whereas the unmanaged dll does not - and actually uses the last char (which always comes out null from the marshaller).

Any ideas ?

Clarification: I can't just change the SizeConst to 43, because I need to maintain the total size of the message, as well as the position of the next fields in the struct (according to an existing ICD)

Consider the following struct to be sent over TCP to an unmanaged dll

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] public struct FooMessage { [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 42)] public string foo; //More fields... } 

Using the following function (credit to Cheeso):

public byte[] RawSerialize( T item ) { int rawSize = Marshal.SizeOf( typeof(T) ); IntPtr buffer = Marshal.AllocHGlobal( rawSize ); Marshal.StructureToPtr( item, buffer, false ); byte[] rawData = new byte[ rawSize ]; Marshal.Copy( buffer, rawData, 0, rawSize ); Marshal.FreeHGlobal( buffer ); return rawData; } 

Problem: The marshaller assumes foo is a null terminated string, whereas the unmanaged dll does not - and actually uses the last char (which always comes out null from the marshaller).

Any ideas ?

Clarification: I can't just change the SizeConst to 43, because I need to maintain the total size of the message, as well as the position of the next fields in the struct (according to an existing ICD)

deleted 2 characters in body
Source Link
Ohad Schneider
  • 38.5k
  • 16
  • 178
  • 212

Consider the following struct to be sent over TCP to an unmanaged dll

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] public struct FooMessage { [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 42)] public string foo; //More fields... } 

Using a the following function (credit to Cheeso):

public byte[] RawSerialize( T item ) { int rawSize = Marshal.SizeOf( typeof(T) ); IntPtr buffer = Marshal.AllocHGlobal( rawSize ); Marshal.StructureToPtr( item, buffer, false ); byte[] rawData = new byte[ rawSize ]; Marshal.Copy( buffer, rawData, 0, rawSize ); Marshal.FreeHGlobal( buffer ); return rawData; } 

Problem: The marshaller assumes foo is a null terminated string, whereas the unmanaged dll does not - and actually uses the last char (which always comes out null from the marshaller).

Any ideas ?

Clarification: I can't just change the SizeConst to 43, because I need to maintain the total size of the message, as well as the position of the next fields in the struct (according to an existing ICD)

Consider the following struct to be sent over TCP to an unmanaged dll

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] public struct FooMessage { [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 42)] public string foo; //More fields... } 

Using a the following function (credit to Cheeso):

public byte[] RawSerialize( T item ) { int rawSize = Marshal.SizeOf( typeof(T) ); IntPtr buffer = Marshal.AllocHGlobal( rawSize ); Marshal.StructureToPtr( item, buffer, false ); byte[] rawData = new byte[ rawSize ]; Marshal.Copy( buffer, rawData, 0, rawSize ); Marshal.FreeHGlobal( buffer ); return rawData; } 

Problem: The marshaller assumes foo is a null terminated string, whereas the unmanaged dll does not - and actually uses the last char (which always comes out null from the marshaller).

Any ideas ?

Clarification: I can't just change the SizeConst to 43, because I need to maintain the total size of the message, as well as the position of the next fields in the struct (according to an existing ICD)

Consider the following struct to be sent over TCP to an unmanaged dll

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] public struct FooMessage { [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 42)] public string foo; //More fields... } 

Using the following function (credit to Cheeso):

public byte[] RawSerialize( T item ) { int rawSize = Marshal.SizeOf( typeof(T) ); IntPtr buffer = Marshal.AllocHGlobal( rawSize ); Marshal.StructureToPtr( item, buffer, false ); byte[] rawData = new byte[ rawSize ]; Marshal.Copy( buffer, rawData, 0, rawSize ); Marshal.FreeHGlobal( buffer ); return rawData; } 

Problem: The marshaller assumes foo is a null terminated string, whereas the unmanaged dll does not - and actually uses the last char (which always comes out null from the marshaller).

Any ideas ?

Clarification: I can't just change the SizeConst to 43, because I need to maintain the total size of the message, as well as the position of the next fields in the struct (according to an existing ICD)

moving to separate answer; deleted 208 characters in body
Source Link
Ohad Schneider
  • 38.5k
  • 16
  • 178
  • 212

Consider the following struct to be sent over TCP to an unmanaged dll

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] public struct FooMessage { [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 42)] public string foo; //More fields... } 

Using a the following function (credit to Cheeso):

public byte[] RawSerialize( T item ) { int rawSize = Marshal.SizeOf( typeof(T) ); IntPtr buffer = Marshal.AllocHGlobal( rawSize ); Marshal.StructureToPtr( item, buffer, false ); byte[] rawData = new byte[ rawSize ]; Marshal.Copy( buffer, rawData, 0, rawSize ); Marshal.FreeHGlobal( buffer ); return rawData; } 

Problem: The marshaller assumes foo is a null terminated string, whereas the unmanaged dll does not - and actually uses the last char (which always comes out null from the marshaller).

Any ideas ?

Clarification: I can't just change the SizeConst to 43, because I need to maintain the total size of the message, as well as the position of the next fields in the struct (according to an existing ICD)

Edit - The only workaround I can find is

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] public struct FooMessage { // use this for non-null-terminated strings // use default encoder to convert to and from string [MarshalAs(UnmanagedType.ByValArray, SizeConst=42)] public char[] foo; //More fields... } 

Also a similar solution by TCP expert Stephen Cleary

Consider the following struct to be sent over TCP to an unmanaged dll

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] public struct FooMessage { [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 42)] public string foo; //More fields... } 

Using a the following function (credit to Cheeso):

public byte[] RawSerialize( T item ) { int rawSize = Marshal.SizeOf( typeof(T) ); IntPtr buffer = Marshal.AllocHGlobal( rawSize ); Marshal.StructureToPtr( item, buffer, false ); byte[] rawData = new byte[ rawSize ]; Marshal.Copy( buffer, rawData, 0, rawSize ); Marshal.FreeHGlobal( buffer ); return rawData; } 

Problem: The marshaller assumes foo is a null terminated string, whereas the unmanaged dll does not - and actually uses the last char (which always comes out null from the marshaller).

Any ideas ?

Clarification: I can't just change the SizeConst to 43, because I need to maintain the total size of the message, as well as the position of the next fields in the struct (according to an existing ICD)

Edit - The only workaround I can find is

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] public struct FooMessage { // use this for non-null-terminated strings // use default encoder to convert to and from string [MarshalAs(UnmanagedType.ByValArray, SizeConst=42)] public char[] foo; //More fields... } 

Also a similar solution by TCP expert Stephen Cleary

Consider the following struct to be sent over TCP to an unmanaged dll

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] public struct FooMessage { [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 42)] public string foo; //More fields... } 

Using a the following function (credit to Cheeso):

public byte[] RawSerialize( T item ) { int rawSize = Marshal.SizeOf( typeof(T) ); IntPtr buffer = Marshal.AllocHGlobal( rawSize ); Marshal.StructureToPtr( item, buffer, false ); byte[] rawData = new byte[ rawSize ]; Marshal.Copy( buffer, rawData, 0, rawSize ); Marshal.FreeHGlobal( buffer ); return rawData; } 

Problem: The marshaller assumes foo is a null terminated string, whereas the unmanaged dll does not - and actually uses the last char (which always comes out null from the marshaller).

Any ideas ?

Clarification: I can't just change the SizeConst to 43, because I need to maintain the total size of the message, as well as the position of the next fields in the struct (according to an existing ICD)

added 148 characters in body
Source Link
Ohad Schneider
  • 38.5k
  • 16
  • 178
  • 212
Loading
added 8 characters in body
Source Link
Ohad Schneider
  • 38.5k
  • 16
  • 178
  • 212
Loading
added 401 characters in body; added 126 characters in body
Source Link
Ohad Schneider
  • 38.5k
  • 16
  • 178
  • 212
Loading
added 239 characters in body
Source Link
Ohad Schneider
  • 38.5k
  • 16
  • 178
  • 212
Loading
Source Link
Ohad Schneider
  • 38.5k
  • 16
  • 178
  • 212
Loading