본문 바로가기

컴퓨터/Delphi

[C포팅] 델파이로 익명 공용체 포팅 방법

최근 한 프로젝트로 인해 C언어 라이브러리를 델파이로 포팅할 일이 있었다.

대부분 구글링을 통해서 쉽게 변환할 수 있었는데 익명 공용체의 포팅에서 쉽게 알기 어려웠던 점이 있어 포스팅으로 남긴다.


먼저 구조체는 아래와 같이 사용된다.


 C Style

 Delphi Style

struct MyStruct {

int a;

char b;

double c;

}

MyStruct = record a:integer; b:char; c:double; end;


그리고 공용체는 아래와 같이 사용된다.


 C Style

 Delphi Style

struct MyStruct {

union {

int a;

char b;

double c;

} u;

}

MyStruct = record

case Integer of 0: (a:integer); 1: (b:char); 2: (c:double); end;


위와 같이 C에서 델파이로의 변환이 어렵지 않게 이뤄질 수 있는데 문제는 다음의 코드에서 발생했다.



#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];
    }; // 익명 공용체
    uint8_t type; // 공용체 이후 unsigned 8-bit int
}) param_union_t;


익명이 아니라면 공용체 레코드를 별도로 만들어서 아래와 같이 해결할 수 있지만



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

...

...
end; param_union_t = packed record u: union_t; UInt8 type; end;


익명 구조체이므로 어떻게 해결해야할지 Stack Overflow에 질문을 했었다.

(link: https://stackoverflow.com/questions/54613312/how-do-i-convert-a-c-union-to-delphi )


문의 결과 익명 공용체 이후에 기술되는 변수들은 가장 사이즈가 큰 case 뒤에 같이 서술하면 된단다.

동일한 byte 크기의 case가 여럿이면 그중 아무곳에나 서술하면 된다고 한다.



 param_union_t = packed record
  case Integer of
    0: (param_float: Single);
    1: (param_int32: Int32);
    2: (param_uint32: UInt32;
        &type: UInt8);
    ...
    ...
end;