考虑通过TCP将以下结构发送到非托管dll
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
public struct FooMessage
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 42)]
public string foo;
//More fields...
}
使用以下功能(贷记给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;
}
问题:marshaller假设foo是一个以空字符结尾的字符串,而非托管dll则没有 - 并且实际上使用了最后一个字符(它总是从编组器中返回null)。
有什么想法吗?
澄清:我不能只将SizeConst更改为43,因为我需要保持消息的总大小,以及结构中下一个字段的位置(根据现有的ICD)
答案 0 :(得分:2)
由于没有发布其他答案,这里是我发现的workaround
[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...
}
TCP专家Stephen Cleary的similar解决方案
答案 1 :(得分:1)
您可以使用StructLayout(LayoutKind.Explicit ...)并使用[FieldOffset( n )]标记每个字段。这将允许您将SizeConst值增加到43,并仍然将下一个字段标记为从偏移量42开始。编组将编组42个字符串并忽略附加空终止符的第43个字节
答案 2 :(得分:0)
你有两个,只有两个选择:
其中一个,请选择。
- b