Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-pascal / 2009-01

Problem with c header conversion

3 messages · 3 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

gabor

Hello,

I'm trying to convert c header code from "Windows Mobile API 5" to pascal and I'm getting wrong size of converted record:

original c header:

typedef struct _DDPIXELFORMAT
{
     DWORD	dwSize;
     DWORD	dwFlags;
     DWORD	dwFourCC;
     union
     {
	DWORD	dwRGBBitCount;
	DWORD	dwYUVBitCount;
	DWORD	dwAlphaBitDepth;
     };
     union
     {
	DWORD	dwRBitMask;
	DWORD	dwYBitMask;
     };
     union
     {
	DWORD	dwGBitMask;
	DWORD	dwUBitMask;
     };
     union
     {
	DWORD	dwBBitMask;
	DWORD	dwVBitMask;
	};
     union
     {
	DWORD	dwRGBAlphaBitMask;
     };
} DDPIXELFORMAT, * LPDDPIXELFORMAT;

and my pascal conversion:

PDDPixelFormat = ^TDDPixelFormat;
   _DDPIXELFORMAT = record
     dwSize: DWORD;
     dwFlags: DWORD;
     dwFourCC: DWORD;
     case Integer of
       0: (
           dwRGBBitCount : DWORD;
           dwYUVBitCount : DWORD;
           dwAlphaBitDepth : DWORD;
           );
       1: (
           dwRBitMask : DWORD;
           dwYBitMask : DWORD;
           );
       2: (
           dwGBitMask : DWORD;
           dwUBitMask : DWORD;
           );
       3: (
           dwBBitMask : DWORD;
           dwVBitMask : DWORD;
           );
       4: (
           dwRGBAlphaBitMask: DWORD;
          );
   end;
   DDPIXELFORMAT = _DDPIXELFORMAT;
   TDDPixelFormat = _DDPIXELFORMAT;

embedded visual c++ 4 returns sizeof(_DDPIXELFORMAT) = 32

free pascal 2.2.2 arm/wince target returns sizeof(_DDPIXELFORMAT) = 24

When I retrive these structure from Windows, field dwSize = 32

Where is problem? Maybe I shuld use special compiler directive or switch?

Michal

p.s. sorry for my bad english

dmitry boyarintsev
to gabor

each "union" is a separate case for pascal. another thing is that the structure is quite agly and does not reveale the logicals usage. The problem is that pascal does not allow you to use multiple cases in single record, that would require you to declare additional types.

  _PFColorSize = record
  case Integer of
    0: (dwRGBBitCount : DWORD);
    1: (dwYUVBitCount : DWORD);
    2: (dwAlphaBitDepth : DWORD);
  end;
  _PFColorMask = record
  case Integer of
    0: (
       dwRBitMask : DWORD;
       dwGBitMask : DWORD;
       dwBBitMask : DWORD;
       dwRGBAAlphaBitMask: DWORD;
       );
    1: (dwYBitMask : DWORD;
        dwUBitMask : DWORD;
        dwVBitMask : DWORD
    );
  end;
  PDDPixelFormat = ^TDDPixelFormat;
 _DDPIXELFORMAT = record
   dwSize: DWORD;
   dwFlags: DWORD;
   dwFourCC: DWORD;
   _size : PFColorSize;
   _mask : PFColorMask;
 end;
 DDPIXELFORMAT = _DDPIXELFORMAT;
 TDDPixelFormat = _DDPIXELFORMAT;
Jonas Maebe
to gabor: I'm trying to convert c header code from "Windows Mobile API 5" to pascal and I'm getting…
gabor wrote 21 lines
I'm trying to convert c header code from "Windows Mobile API 5" to pascal and I'm getting wrong size of converted record: original c header: typedef struct _DDPIXELFORMAT { DWORD dwSize; DWORD dwFlags; DWORD dwFourCC; union { DWORD dwRGBBitCount; DWORD dwYUVBitCount; DWORD dwAlphaBitDepth; }; union { DWORD dwRBitMask; DWORD dwYBitMask; };

[snip]

and my pascal conversion:

"union" in C means that the fields inside this union{..} block all start at the same address, but whatever comes after the union{} block follows all of those fields. Your translation does exactly the inverse: it makes all union blocks start at the same address, but puts the fields inside the union blocks after each other.

I don't think you can create sequential unnamed variant parts in Pascal records like the above C struct though, but you can get the same layout and usage by doing this:

PDDPixelFormat = ^TDDPixelFormat;
  _DDPIXELFORMAT = record
    dwSize: DWORD;
    dwFlags: DWORD;
    dwFourCC: DWORD;
    case Integer of
      0: (
          dwRGBBitCount : DWORD;
         );
      1: (
          dwYUVBitCount : DWORD;
         );
      2: (
          dwAlphaBitDepth : DWORD;
          case Integer of
           0: (
               dwRBitMask : DWORD;
              );
           1: (
               dwYBitMask : DWORD;
               case Integer of
                 0: (
                     dwGBitMask : DWORD;
                    );
                 1: (
                     dwUBitMask : DWORD;
                     case Integer of
                       0: (
                           dwBBitMask : DWORD;
                          );
                       1: (
                           dwVBitMask : DWORD;
                           case Integer of
                             0: (
                                 dwRGBAlphaBitMask: DWORD;
                                );
                          );
                    );
              );
          );
    end;

In this case it's easy because in each union every field has the same size. If that weren't the case, you would have to put the nested variant parts after the largest field of each variant. Or you could put the variant parts in separate record types and then declare fields of these types (which is cleaner, but then when accessing the fields you will have to add the record field names).

Jonas