Sign in to follow this  
bpoint

Unity can't #define #pragma pack?

Recommended Posts

Hello all, I am trying to find a way to set up structure packing using #define macros while also being compiler-independant. Ideally, something like this would be great:
MYSTRUCTPACK(1) struct
{
    char foo;
    int bar;
} hoge;

However, MSVC (and other compilers) use a #pragma with a push and pop syntax, rather than a _declspec like they use for alignment, so I've resigned myself that this is probably the best I'd ever be able to do:
MYSTRUCTPACK_BEGIN(1)

struct
{
    char foo;
    int bar;
} hoge;

MYSTRUCTPACK_END()


Unfortunately, MSVC doesn't like me using a #define to declare #pragma pack:
#define MYSTRUCTPACK_BEGIN(x)     #pragma pack(push, x)    // error C2162: expected macro formal parameter
After much fruitless searching on Google, I did manage to find one thread here on gamedev where Null and Void pointed out how CPT handles this issue. The only problem with using a #include to wrap a structure is that I wouldn't be able to specify the desired packing (1, 2, 4, 8, 16, etc) unless I created multiple include files each with a different values. That post was made back in 2002. Is there any better way to do this 4 years later that I'm just not aware of?

Share this post


Link to post
Share on other sites
Quote:
Original post by Roboguy
You cannot define a macro which uses the preprocessor.


What?


// ---------------------------------------------------------------------------
// use the preprocessor to turn a symbol into a string
#define STR(x) #x
#define STRING(x) STR(x)






bpoint, it might require using a set of 8 headers - before and after for each possibility.


Share this post


Link to post
Share on other sites
Quote:
Original post by LessBread
Quote:
Original post by Roboguy
You cannot define a macro which uses the preprocessor.


What?

*** Source Snippet Removed ***


I meant you can't issue preprocessor directives, like #pragma in a macro.

Share this post


Link to post
Share on other sites
Okay, I've played with it some more and managed to get a bit farther. MSDN docs say:
Quote:
Following #pragma, write any text that the translator can parse as preprocessing tokens. The argument to #pragma is subject to macro expansion.


So I can whip up something like this:

#define MYPACK_BEGIN(x)				pack(push, x)
#define MYPACK_END pack(pop)

#pragma MYPACK_BEGIN(1)

struct
{
char foo;
int bar;
} hoge;

#pragma MYPACK_END


This would also work for other compilers, assuming that they allow macro substitution after the #pragma. However, this leaves out GCC which decided to be "different" and use the __attribute__ syntax instead of a #pragma...

I then decided to see if I could use string substitution in a macro to create a header filename like so:

#define MYPACK2(x)					"PackHeader" #x ".h"

#include MYPACK2(4) // warning C4067: unexpected tokens following preprocessor directive - expected a newline
// fatal error C1083: Cannot open include file: 'PackHeader': No such file or directory


But this doesn't seem to work either.

Does anyone have any other ideas (even if they are hackish)? Or am I just going to have to break down and make include files for each packing alignment I need, like LessBread has suggested?

Thanks for the tips, guys.

Share this post


Link to post
Share on other sites
Quote:
Original post by bpoint
However, this leaves out GCC which decided to be "different" and use the __attribute__ syntax instead of a #pragma...


No it didn't, #pragmas are compiler-specific.

Share this post


Link to post
Share on other sites
Quote:
Original post by Roboguy
No it didn't, #pragmas are compiler-specific.


Indeed they are. However, GCC certainly could have implemented structure packing the same way every other compiler has done it, rather than being different.

Actually, I prefer the __attribute__ syntax myself. But unfortunately everyone else uses #pragma already...

Share this post


Link to post
Share on other sites
Quote:
Original post by Roboguy
Quote:
Original post by LessBread
Quote:
Original post by Roboguy
You cannot define a macro which uses the preprocessor.


What?

*** Source Snippet Removed ***


I meant you can't issue preprocessor directives, like #pragma in a macro.


It seems to me that #pragma is a compiler directive not a preprocessor directive. However, microsoft appears to categorizes it as a preprocessor directive, which might explain why bpoint ran in to trouble with MSVC. I don't have a copy of the standard at hand to check, maybe someone else does.

Share this post


Link to post
Share on other sites
It seems that since gcc-4.0, gcc supports #pragma pack for compatibility with Win32.

If that's the case then all I need to is ensure MetroWorks and GCC will allow me to #define the text after the pragma. I'm not at home now, so I'll try testing this theory later tonight.

Share this post


Link to post
Share on other sites
Uhm, it seems you didn't read the MSDN, or i am missing something... __declspec(align(X)) seems to be the thing you are looking for, or am i wrong?


On the other hand, if you want to go with includes, then your attempt (bellow) is wrong.

#define MYPACK2(x) "PackHeader" #x ".h"
#include MYPACK2(4)


What you should do is something like this:

#define STRINGIZE(X) #X
#define PACK(X) STRINGIZE(pack##X##.h)
#define PACK_END "packend.h"



EDIT: fixed the link...

EDIT2: added includes

[Edited by - Paulius Maruska on August 17, 2006 3:32:33 AM]

Share this post


Link to post
Share on other sites
Quote:
Original post by Paulius Maruska
Uhm, it seems you didn't read the MSDN, or i am missing something... __declspec(align(X)) seems to be the thing you are looking for, or am i wrong?


Structure packing is not the same as alignment.

Structure packing ensures that variables within a structure are aligned to a specific memory address. In my example above, sizeof(hoge) would be 5 if packing was set to 1, or 8 if packing was set to 4.

Alignment (using __declspec) is what aligns the variable itself to a specific memory address. For example, I could align my structure to 16 bytes, so that anywhere it was used the address would be properly aligned.

Alignment can also be specified along with packing, so I could feasibly have a 5 byte sized struct that is 16 byte aligned in memory.

Hope this helps. :)

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
You can use _Pragma operator to do this. It is defined in standard (#16.9 Pragma operator).
I have tested it with GCC 4.2.0,4.0.2,4.1.0,3.4.5 and 3.3.6 and it works perfectly


#include <cstdio>

#define PACK _Pragma("pack(push,1)")
#define UNPACK _Pragma("pack(pop)")

PACK

struct MyStruct {
char m_test[3];
int m_test2;
short m_test3;
};

UNPACK

int main(void) {
printf("sizeof(struct MyStruct): %u\n",sizeof(struct MyStruct));
return 0;
}


Share this post


Link to post
Share on other sites
Quote:
Original post by bpoint
Structure packing is not the same as alignment.
<...>
Hope this helps. :)


Sorry, i'l note that for the future.

Quote:
Original post by AP
You can use _Pragma operator to do this. It is defined in standard (#16.9 Pragma operator).
I have tested it with GCC 4.2.0,4.0.2,4.1.0,3.4.5 and 3.3.6 and it works perfectly

It doesn't work in MSVC8 - i've tested it...


So anyway, you can still use something like this (as in my previous post):

#define STRINGIZE(X) #X
#define PACK(X) STRINGIZE(pack##X##.h)
#define PACK_END "packend.h"

#include PACK(2)
struct MyStruct {
int x, y, z;
double a, b, c;
};
#include PACK_END


Note, however, Visual C++ will issue a warning C4103 if header changes packing. Don't know if other compilers complains about it.

Share this post


Link to post
Share on other sites
That would be an absolutely ideal solution if VS2005 (and everybody else) supported it...
Quote:
error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
error C2440: 'initializing' : cannot convert from 'const char [13]' to 'int'
error C2143: syntax error : missing ';' before '<class-head>'
error C2448: '_Pragma' : function-style initializer appears to be a function definition


Unfortunately I can't just make a special case for GCC since I need to have a #pragma before the #defined pack macro.

Maybe the next generation of compilers will have a better (and more standardized) way of handling this. But I'm not holding my breath. :)

Share this post


Link to post
Share on other sites
I belive Microsoft has several headers called things like "pshpk8" and "pshpk16" and so on, which does exactly what you described for #includes.

Personally, I'd just go with the #includes, it's probably easiest.

Share this post


Link to post
Share on other sites
Quote:
Original post by Evil Steve
Personally, I'd just go with the #includes, it's probably easiest.


Yep, that really looks like the best choice. Since CodeWarrior uses #pragma option align=[some text], I wouldn't be able to properly set the structure packing with the MetroWerks compiler. Also using headers allows me to disable that pesky warning under MSVC. :)

Thanks to Paulius Maruska! I didn't realize my preprocessor stringizations were wrong.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this