来自delphi打包记录的正确结构布局

我正在将delphi应用程序转换为C#。 有一堆打包的记录,根据几周前我问过的类似问题,转换成课程会更好。 但是,我被告知我需要将它们转换为结构体,我可以使用一些帮助。 我将使用BinaryReader从文件中读取并将值分配给结构体内的字段。

*注意,我正在阅读的文件是使用Delphi和打包记录制作的。

这是一个示例结构:

delphi:

 Testrec = packed record now: TDateTime; MinLat: longint; MinLong: longint; Firsttime: TDateTime; MinAlt: single; MinFirst: single; MinDepth: single; MinSpeed: single; MinBot: single; res3: single; res4: single; res5: single; res6: single; MaxLat: longint; MaxLong: longint; Lasttime: TDateTime; MaxAlt: single; MaxFirst: single; MaxDepth: single; MaxSpeed: single; MaxBot: single; res9: single; res10: single; res11: single; res12: single; DataFlags: longint; ReviewFlags: longint; res13: longint; FirstPost: longint; end; 

这是我的C#版本:

 public struct Testrec { double now; int MinLat; int MinLong; double Firsttime; float MinAlt; float MinFirst; float MinDepth; float MinSpeed; float MinBot; float res3; float res4; float res5; float res6; int MaxLat; int MaxLong; double Lasttime; float MaxAlt; float MaxFirst; float MaxDepth; float MaxSpeed; float MaxBot; float res9; float res10; float res11; float res12; int DataFlags; int ReviewFlags; int res13; int FirstPost; } 

我需要做一个StructLayoutSizeCharSet吗?

编辑:这是有关读取二进制文件的相关delphi代码:

 Testrec Header; HeaderSize = 128; RampStream:=TFileStream.Create(FilePath,fmOpenReadWrite OR fmShareExclusive ); RampStream.Read(Header,HeaderSize); StartTime:=Header.Firsttime; EndTime:=Header.Lasttime; 

以下是我设置二进制阅读器的方法:

 RampStream = new BinaryReader(new FileStream(RampName, FileMode.Open, FileAccess.ReadWrite, FileShare.None)); 

您需要指定顺序布局和包值1。

 [StructLayout(LayoutKind.Sequential, Pack = 1)] 

由于没有文本成员,因此无需指定CharSet 。 你应该让编译器计算结构的大小。 现在,指定了这个,您将能够将整个记录读入内存,然后将其直接blit到此C#结构上。 像这样:

 Testrec ReadRecFromStream(Stream stream) { byte[] buffer = new byte[Marshal.SizeOf(typeof(Testrec))]; stream.Read(buffer, 0, buffer.Length); GCHandle handle = GCHandle.Alloc(buffer, GCHandleType.Pinned); try { return (Testrec)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(Testrec)); } finally { handle.Free(); } } 

但是,您说过您将一次读取成员并分配给C#结构中的相应字段。 在这种情况下,不需要寻求二进制布局等价,因为您不会使用它。 如果您要一次读取一个成员,则不需要StructLayout属性。 您无需声明任何未使用的成员。 您可以在输入点将Delphi日期时间值转换为适当的C#数据类型,依此类推。

因此,您需要决定是否要寻求这些结构的二进制布局等效性。