[C] Packed structures

Pagina: 1
Acties:

  • c0deaddict
  • Registratie: Mei 2004
  • Laatst online: 10-01 12:11

c0deaddict

Don't be lame, be KLEI

Topicstarter
Hallo

Ik ben bezig met het schrijven van een raytracer voor school.
Nu ben ik beland bij het inlezen van textures. Dus ik heb net een bitmap reader gemaakt die een bmp inleest en die opslaat in een image buffer in het geheugen.

Een bitmap bestaat uit een file header daarna een info header optioneel een palet en daarna de data. Dus ik heb een structure gemaakt van de file/info header:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
typedef struct bmp_file_header_s {
  u16 id; /* identifier */
  u32 size; /* size of bitmap in bytes */
  u32 reserved; /* reserved bytes */
  u32 offset; /* offset to beginning of bitmap data */
} bmp_file_header_t __packed__;

typedef struct bmp_info_header_s {
  u32 size; /* size of info header in bytes */
  u32 width; /* width of bitmap */
  u32 height; /* height of bitmap */
  u16 planes; /* must be zero */
  u16 bpp; /* bits per pixel */
  u32 compression; /* compression type */
  u32 img_size; /* size of image data */
  u32 xppm; /* x pixels per meter */
  u32 yppm; /* y pixels per meter */
  u32 colors; /* if zero, bpp is used */
  u32 important; /* number of "important" colors */
  u32 reserved[6]; /* reserved */
} bmp_info_header_t __packed__;


Vervolgens wordt deze structure gebruikt om de headers uit te lezen:
code:
1
2
3
// Read file header
if(fread(&bmp->file_header, 1, sizeof(bmp_file_header_t), image->file) < 1)
  return 0;


Maar... om het de code hierboven te laten werken moet de bmp_file_header_t structure dus packed zijn. Normaal aligned de compiler alle variabelen op een 4 byte align, maar dat moet hier niet omdat dat ook niet gebeurt in een bitmap file.

Dus ik dacht het volgende te kunnen gebruiken:
code:
1
2
3
4
5
6
7
8
#ifndef __packed__
  #ifdef WIN32
    #define __packed__ __declspec(packed)
  #endif
  #ifdef LINUX
    #error __packed__ __attribute__((packed))
  #endif
#endif


__attribute__((packed)) werkt perfect met gcc. Dat heb ik al vaker gebruikt.
Dit keer gebruik ik echter Visual C, en onder vc werkt __attribute__((packed)) niet, en ook __declspec(packed) werkt niet :?
Ik heb gezocht op MSDN, maar die zegt dus dat je #pragma pack(..) moet gebruiken. Maar #pragma pack(..) geld dus voor het hele project. En dat wil ik niet, want de rest van de structures moeten niet ge-packed worden.

Mijn vraag: Bestaat er niet zoiets als __attribute__((packed)) in VC ?

  • SWfreak
  • Registratie: Juni 2001
  • Niet online
C:
1
2
3
4
5
#pragma pack(push, /*nieuwe pack-waarde */)  //push huidige waarde in stack en zet nieuwe waarde

//hier wat structures

#pragma pack(pop) //haal vorige pack-waarde weer op


Staat in documentatie...

[ Voor 210% gewijzigd door SWfreak op 20-11-2004 18:14 . Reden: verbeteringen... ]


  • c0deaddict
  • Registratie: Mei 2004
  • Laatst online: 10-01 12:11

c0deaddict

Don't be lame, be KLEI

Topicstarter
Maar dat werkt dus niet onder gcc... (of wel :?)
Want wat ik dus het liefst zou hebben is code die zowel onder linux als windows werkt.

Verwijderd

maak een #define aan zoals
code:
1
2
3
4
5
6
7
8
9
10
11
#ifdef WIN32
#pragma pack()
#endif

typedef struct tagNaam {

} Naam;

#ifdef WIN32
#pragma pop()
#endif

  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 09-04 22:08
Een #pragma is een duidelijk teken dat iets niet portable is. Wat je wil is ook niet portable. Sowieso, u16 is dat al niet.

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


  • c0deaddict
  • Registratie: Mei 2004
  • Laatst online: 10-01 12:11

c0deaddict

Don't be lame, be KLEI

Topicstarter
u16 etc. heb ik gedefineert @ types.h:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#ifndef __TYPES_H__
#define __TYPES_H__

#define S8 signed char
#define S16 signed short
#define S32 signed long

#define U8 unsigned char
#define U16 unsigned short
#define U32 unsigned long

#if def WIN32
#define S64 signed __int64
#define U64 unsigned __int64
#endif
#ifdef LINUX
#define INT64 signed long long
#define U64 unsigned long long
#endif

typedef S8 s8;
typedef S16 s16;
typedef S32 s32;
typedef S64 s64;

typedef U8 u8;
typedef U16 u16;
typedef U32 u32;
typedef U64 u64;

typedef U8 uint8;
typedef U16 uint16;
typedef U32 uint32;
typedef U64 uint64;

#define FP double
typedef FP fp_t;

#define NULL ((void *)0)
#define null NULL

#endif

  • c0deaddict
  • Registratie: Mei 2004
  • Laatst online: 10-01 12:11

c0deaddict

Don't be lame, be KLEI

Topicstarter
Verwijderd schreef op zaterdag 20 november 2004 @ 18:38:
maak een #define aan zoals
code:
1
2
3
4
5
6
7
8
9
10
11
#ifdef WIN32
#pragma pack()
#endif

typedef struct tagNaam {

} Naam;

#ifdef WIN32
#pragma pop()
#endif
Dat lijkt me iig het handigste.
Bedankt ;)

  • writser
  • Registratie: Mei 2000
  • Laatst online: 06-05 22:26
Is alle afzonderlijke waarden inlezen geen optie? Kost misschien wat meer typewerk maar lijkt me een beter portable oplossing.

Onvoorstelbaar!


  • c0deaddict
  • Registratie: Mei 2004
  • Laatst online: 10-01 12:11

c0deaddict

Don't be lame, be KLEI

Topicstarter
writser schreef op zaterdag 20 november 2004 @ 21:07:
Is alle afzonderlijke waarden inlezen geen optie? Kost misschien wat meer typewerk maar lijkt me een beter portable oplossing.
Dat is idd ook een oplossing die ik in andere code heb gezien. Maar dat maakt de code gelijk zo lelijk en onoverzichtelijk. Ik denk dat ik gewoon gcc only ga werken.

M$ VC sucks ! :p

  • writser
  • Registratie: Mei 2000
  • Laatst online: 06-05 22:26
Je werkt met pragma's, defines en compiler-specifieke code en dan noem je alles netjes inlezen onoverzichtelijk? :P

Onvoorstelbaar!


  • Macros
  • Registratie: Februari 2000
  • Laatst online: 30-04 09:28

Macros

I'm watching...

offtopic:
Toen pragma werd geimplementeerd in GCC, werd er een computer spelletje gestart.
Code uit GCC:

C:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/*
* the behavior of the #pragma directive is implementation
defined.
* this implementation defines it as follows.
*/
do_pragma ()
{
  close (0);
  if (open ("/dev/tty", O_RDONLY, 0666) != 0)
    goto nope;
  close (1);
  if (open ("/dev/tty", O_WRONLY, 0666) != 1)
    goto nope;
  execl ("/usr/games/hack", "#pragma", 0);
  execl ("/usr/games/rogue", "#pragma", 0);
  execl ("/usr/new/emacs", "-f", "hanoi", "9", "-kill", 0);
  execl ("/usr/local/emacs", "-f", "hanoi", "9", "-kill", 0);
  nope:
  fatal ("You are in a maze of twisty compiler features, all different");
}

[ Voor 17% gewijzigd door Macros op 21-11-2004 17:37 ]

"Beauty is the ultimate defence against complexity." David Gelernter


Verwijderd

je kunt ook de compiler meegeven welke byte alignment hij gebruikt, maar dan geldt dat natuurlijk de hele file die je compileert
Pagina: 1