Seunghyun Baek
Seunghyun Baek

Reputation: 55

How do I convert a C union to delphi?

I am converting the C library to Delphi. I have a problem converting the code below. This is the structure used for communications, so the order must be correct.

Delphi

Tparam_union_params_t = packed record
  case Integer of
    0: (param_float:single);
    1: (param_int32:Int32);
    2: (param_uint32:UInt32);
    ...
    ...
end;

Tparam_union_t = packed record
  param:Tparam_union_params_t // This method requires var name.
  type:UInt8;
end;

C Lang

#ifdef __GNUC__
  #define PACKED( __Declaration__ ) __Declaration__ __attribute__((packed))
#else
  #define PACKED( __Declaration__ ) __pragma( pack(push, 1) ) __Declaration__ __pragma( pack(pop) )
#endif

PACKED(
typedef struct param_union {
    union {
        float param_float;
        int32_t param_int32;
        uint32_t param_uint32;
        int16_t param_int16;
        uint16_t param_uint16;
        int8_t param_int8;
        uint8_t param_uint8;
        uint8_t bytes[4];
    }; // This no-named union. no-named is important.
    uint8_t type;
}) param_union_t;

My method requires var name but original c code is no-named. How do I convert anonymous union or structure in C to Delphi?

Upvotes: 3

Views: 357

Answers (1)

Rudy Velthuis
Rudy Velthuis

Reputation: 28836

What you have is not bad, but in my article Pitfalls of converting I describe a slightly nicer technique to handle such a union without a name:

param_union_p = ^param_union_t;
param_union_t = packed record
  case Integer of
    0: (param_float: Single);
    1: (param_int32: Int32);
    2: (param_uint32: UInt32;    // add the members after the union to the largest branch.
        &type: UInt8);
    3: (param_int16: Int16);
    ...
    ...
end;
PParamUnion = ^TParamUnion;
TParamUnion = param_union_t;

Instead of in the UInt32 branch it could also be added to the Single or Int32 branch of the same size. That would still result in the same memory layout as the struct in C, with &type at offset 4, and the size of the record being 5, and that is all that counts. Just take a look at the diagram in the article for clarification:

enter image description here

This way, there is no need to give the union part its own type and its own name. If you don't trust the "trick", use the code I give in the same article to check the offsets in C and in Delphi.

Borland and Embarcadero, and also Delphi-JEDI, use(d) the same trick to translate anonymous unions, and the Delphi TVarRec (for array of const parameters) and TVarType (for Variants) records are built that way too.

Upvotes: 6

Related Questions