Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
422 views
in Technique[技术] by (71.8m points)

c# - Proper struct layout from delphi packed record

I'm converting a delphi app to C#. There are a bunch of packed records, and according to a similar question I asked a few weeks ago, it would be better to convert to classes. However, I'm told I need to convert them to structs, and I could use some help. I'm going to be using a BinaryReader to read from a file and assign values to the fields inside of the structs.

*Note, the file I'm reading from was made using Delphi and packed records.

Here's an example struct:

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;

Here's my C# version:

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

Do I need to do a StructLayout, Size, and CharSet?

Edit: Here's the relevant delphi code regarding the reading of the binary file:

Testrec Header;
HeaderSize = 128;

RampStream:=TFileStream.Create(FilePath,fmOpenReadWrite OR fmShareExclusive );

RampStream.Read(Header,HeaderSize);
StartTime:=Header.Firsttime;
EndTime:=Header.Lasttime;

Here's how I set up my Binary Reader:

RampStream = new BinaryReader(new FileStream(RampName, FileMode.Open, FileAccess.ReadWrite, FileShare.None));
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

You need to specify sequential layout and a pack value of 1.

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

Since there are not textual members, you need not specify CharSet. And you should let the compiler calculate the size of the struct. Now, having specified this you will be able to read the entire record into memory, and then blit it directly onto this C# struct. Like so:

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();
    }
}

However, you said that you were going to read on member at a time and assign to the corresponding field in the C# struct. In that case there's no need to seek binary layout equivalence since you won't be making any use of that. If you are going read one member at a time then you do not need a StructLayout attribute. You don't need to declare any unused members. You can convert the Delphi date time values into the appropriate C# data types at the point of input and so on.

So, you do need to make up your mind as to whether or not you are going to seek binary layout equivalence of these structures.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...