Converting a Delphi Option Record to a C # Structure

Since I am trying to encode a C # application from an existing application, but developed in Delphi, it’s very tough, but managed some, as before, but now I run into a problem ...

Delphi code contains the following code:

type TFruit = record name : string[20]; case isRound : Boolean of // Choose how to map the next section True : (diameter : Single); // Maps to same storage as length False : (length : Single; // Maps to same storage as diameter width : Single); end; 

i.e. the variant record (with the case expression inside) and, accordingly, the record is built and its size, too. On the other hand, I am trying to do the same in C # struct, and so far have failed, I hope someone can help me here. So just let me know if it is possible to somehow implement this in C #. Thanks in advance.

+4
source share
3 answers

You can use an explicit structural layout to replicate this entry in Delphi format. However, I would not bother, as it seems unlikely that you really want to assign diameter to the destination to also length and vice versa. This Delphi record declaration looks like it belongs to the mid 1990s Delphi coding type. Modern Delphi code is rarely written this way.

I would just do it like this:

 struct Fruit { string name; bool isRound; float diameter; // only valid when isRound is true float length; // only valid when isRound is false float width; // only valid when isRound is false } 

A more elegant option would be a class with properties for each field of the structure. And you would agree that the getters and seters properties for 3 floats raised exceptions if they were available for an invalid isRound value.

+5
source

Perhaps this will be a trick?

This is NOT a copy and paste solution, note the need to change data offsets and sizes depending on how the Delphi structure is declared and / or aligned.

 [StructLayout(LayoutKind.Explicit)] unsafe struct Fruit { [FieldOffset(0)] public fixed char name[20]; [FieldOffset(20)] public bool IsRound; [FieldOffset(21)] public float Diameter; [FieldOffset(21)] public float Length; [FieldOffset(25)] public float Width; } 
+1
source

It depends on what you are trying to do.

If you're just trying to create an appropriate structure, look at David Heffernan's answer. Nowadays there is little reason to compare two fields on top of each other, if they really do not represent the same thing. (Let's say individual elements or the same elements in an array.)

If you are actually trying to exchange files, you need to look at the ananthonline response lines, but there is a problem with this, which is big enough, I could not put it in a comment:

Not only a problem with Unicode, but also a short Delphi line does not have a corresponding structure in C #, and therefore it is impossible to simply map a field on top of it.

This line [20] actually contains 21 bytes, a single-byte length code, and 20 characters. You must follow the length code, as there is no guarantee that it is outside the specified length - you are likely to find trash there. (Hint: if the record will be written to disk, always loop the field before inserting new data into it. This greatly facilitates checking the file on disk during debugging.)

Thus, you need to declare two fields and write code to process it at both ends.

Since you still need to do this, I would go ahead and write code to handle the rest, to eliminate the need for unsafe code altogether.

+1
source

Source: https://habr.com/ru/post/1397071/


All Articles