My own approach to all struct loading from disk is to use an unsigned char * and macros that read various type sizes from such a byte array with the proper endian order (for example d[0] + d[1] * 256
- d[2] * 65536 + d[3] * 16777216 is a way to load little endian, regardless of architecture the code is running on), assigning to the structs (which may be packed any way the compiler pleases), and
this solves both endian problems and alignment problems.
This means that I can load any file format on any architecture without worries, and can load to different struct formats if I so desire (for example my memory structs often have additional derived
data I calculate after reading in the disk data).
It’s important to understand that misaligned memory access is a crash on many architectures, and runs slower on the rest, so direct memory loading of structs is “highly unwise” to put it mildly, the
problem goes far beyond mere endian swapping.
Even on x86, you can get a crash if you use __m128 (SSE 128bit vector register) at misaligned addresses - although in that case you must also allocate your memory with memalign because malloc won’t
align to 16 byte by default.On 08/15/2011 05:05 PM, Dimiter ‘malkia’ Stanev wrote:
My problem is that packing is done for MSVC compilers, but not for others. Hence my bindings would only work with MSVC compiled DLL.
That’s perfectly fine, but I don’t have way to detect that (unless SDL exports DEFINES - which now is too much)
Or for example the same binding, structure wise won’t work for Linux, and others, and that’s perfectly legal, but I wish if it was not the case. And SDL is already taking some care in that direction
for the events and WMInfo packing different variants in union.
Another solution is to create for each structure accessor method - this would increase the API though (a bit like pixman, cairo, and other gnome libs).
Personally I would just manually align anything up to 64-bit, and worry about 128-bit later (it might come someday :)).
For example:
uint32 something;
void* pointer;
could be better:
uint32 something;
uint32 padding;
void* pointer;
Even if it’s done for the 32-bit code (unless SDL structures are used quite a lot, but even then - they are probably not the most memory efficient representation anyway to begin with).
On 8/15/2011 4:37 PM, William Dyce wrote:
Computers like data to be nicely aligned so it can be accessed easily.
As a result the compiler will insert empty space between structure
members if they are not “packed”. Say a char (1) between two doubles (8)
will end up will 7 bytes of free space after it so it aligns!
That’s as far as I understand things anyway. The pragma macro takes car
of packing for you. Not sure about the args though…
William
On 16 Aug 2011 07:27, “Patrick Baggett” <baggett.patrick at gmail.com <mailto:baggett.patrick at gmail.com>> wrote:
On Mon, Aug 15, 2011 at 4:06 PM, William Langford <unfies at gmail.com <mailto:unfies at gmail.com>> wrote:
On 8/15/2011 3:53 PM, malkia wrote:
Hi guys,
First post here, great group (been reading it for the last month), and
the question:
What is the reason for the msvc specifc pragma pack(push,4) in
begin_code.h/close_code.h?
I wrote FFI bindings for luajit, and had to handle this case
specifically, but I chose to recompile SDL (1.3) without. This way MSVC
build DLL and MINGW one can get exchanged. I don’t have any other
means of
detecting how the actual DLL was compiled.
It’s not a big deal, but if this pragma is no longer needed what would
be the cost of removing it?
It’s a compatibility thing. Lets say you have a file with a header, you
define a struct for the header. If you wanna just fread() the struct
rather
reading it an entry at a time and assigning it to a struct, you make
sure
the struct alignment matches the file header alignments.
Well, sort of…if you are just fwrite()/fread()'ing a struct
ot/from disk,
you get what you deserve, which is a slap to the face.
If SDL is assuming that structures across shared memory spaces or
certain
files have a 4 byte alignment, then they really need to be kept that
way,
otherwise you’ll possibly break things.
Different compilers have different ways of specifying struct / etc
alignment within source files. Some don’t even use #pragma for it 
-Will
To elaborate on that…
The pragmas are there on MSVC to set the internal alignment of structure
members. It is possible to change the default values of these using MSVC
with the /Zpxx option, e.g: /Zp16 to set 16-byte member alignment. This
option* overrides it and specifies that SDL’s structures are* 4 byte
aligned. This actually increases compatibility since nobody can
build/ship
DLLs with incompatible structure alignment/size, regardless of what they
specify on the command line. Similarly, if your app is built using
/Zp8 and
you include SDL’s headers, you don’t want it to mysteriously break
because
your SDL library has 4-byte aligned structures and your app has 8-byte
aligned structures – you expect SDL “just work” and not to have to
recompile all of SDL just because you set /Zp8. So, removing it is
actually
a bad idea if you want to maintain compatibility since then the
sizeof() SDL
structures depends on what command line flags the user specifies when
building their app.
Patrick
SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org
SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org
–
LordHavoc
Author of DarkPlaces Quake1 engine - LadyHavoc's DarkPlaces Quake Modification
Co-designer of Nexuiz - Nexuiz Classic – Alientrap
“War does not prove who is right, it proves who is left.” - Unknown
“Any sufficiently advanced technology is indistinguishable from a rigged demo.” - James Klass
“A game is a series of interesting choices.” - Sid Meier