Questions about StructLayout Pack values

A

active

I have this and it seems to be working OK but now I wonder if the Pack value
shouldn't be 1.

What do you think?

<StructLayout(LayoutKind.Sequential, Pack:=4, CharSet:=CharSet.Auto)> _

Public Structure CHARFORMAT2

Public cbSize As Integer

Public dwMask As Integer

Public dwEffects As Integer

Public yHeight As Integer

Public yOffset As Integer

Public crTextColor As Integer

Public bCharSet As Byte

Public bPitchAndFamily As Byte

....snip

The Marshaller doesn't know enough to remove the alignment additions does
it?

====

for the following Pack:=2 would work, right?

But Pack=1 would also work, yes?

Public Structure BITMAP

Public bmType As Integer

Public bmWidth As Integer

Public bmHeight As Integer

Public bmWidthBytes As Integer

Public bmPlanes As Short

Public bmBitsPixel As Short

Public bmBits As Integer

End Structure

In fact, when dealing with Windows API struc's doesn't make sense to always
use Pack:=1, Why even try to find the maximum value that works? Just use 1.
What do you think about that?



Thanks
 
J

Jack Jackson

In fact, when dealing with Windows API struc's doesn't make sense to always
use Pack:=1, Why even try to find the maximum value that works? Just use 1.
What do you think about that?

1 will work only if the structure doesn't have any holes. For
example:

Public Structure S

Public f1 As Integer
Public f2 As Byte
Public f2 as Integer

will give different result for packing of 1, 2 and 4. I don't know if
Windows API structures ever do this.

I believe the default for Windows is to align fields on the boundary
that is the same as their size (byte on byte boundary, short on even
boundary, 4-byte integer on 4-byte boundary) but I'm not sure how to
specify that here.
 
A

active

I've been assuming that a Windows structs are packed so that there are no
holes.
But if there is structs like the following would there be three bytes unused
after j2 and one unused after j22.


Or would they all be crammed together?

typedef struct junk1

{

DWORD j1;

BYTE j2;

DWORD j3;

}



typedef struct junk2

{

DWORD j21;

BYTE j22;

WORD j23;

}
 
J

Jack Jackson

I'm pretty sure Windows structures have to have items on a boundary
equal to their lengths, because some CPU types (other than i386) can't
load 4 byte on other than a 4-byte boundary.
 
A

active

Jack Jackson said:
I'm pretty sure Windows structures have to have items on a boundary
equal to their lengths, because some CPU types (other than i386) can't
load 4 byte on other than a 4-byte boundary.
I've been looking and almost all satisfy that. But the one below is what
started me wondering. I know for a fact that it is supposed to fits into 14
bytes. Seems like they should have put bfType last and bfOffBits first.

I do believe what you said fits everything else I've seen.

thanks
<StructLayout(LayoutKind.Sequential, Pack:=2)> _

Public Structure BITMAPFILEHEADER

Public bfType As Int16 '19778 = "BM"

Public bfSize As Int32 'Entire file including this header

Public bfReserved1 As Int16

Public bfReserved2 As Int16

Public bfOffBits As Int32 'From the beginning of file (bytes)

End Structure
 
H

Herfried K. Wagner [MVP]

Jack Jackson said:
I'm pretty sure Windows structures have to have items on a boundary
equal to their lengths, because some CPU types (other than i386) can't
load 4 byte on other than a 4-byte boundary.

The Win32 API typically uses structures with their members packed on 4-byte
boundaries. However, there are some exceptions in the Shell API where
members are packed on single-byte boundaries.
 
H

Herfried K. Wagner [MVP]

active said:
What does vb.net do.

I'm wondering when I need to include Pack:

IIRC the default is a packing on 'DWORD'-boundaries (4-byte boundaries).
You need to include 'Pack' when the target system expects another packing,
such as packing on single-byte boundaries.
 
A

active

I've been getting by with things like what's below.

If I understand you correctly this should not work or is just that the
4-byte items must be on 4-byte boundaries?

Or are the Shorts followed by 2 unused bytes?

I do know of a case something like a Short followed by a DWORD, and there
were two extra bytes after the short.

If you have only four bytes must you use Pack:1

How about a Structure containing only 4 Shorts, need Pack:2

Comments?

Thanks
Public Structure PARAFORMAT

Public cbSize As Integer

Public dwMask As Integer

Public wNumbering As Short

Public wReserved As Short

Public dxStartIndent As Integer

Public dxRightIndent As Integer

....

End Structure
 
H

Herfried K. Wagner [MVP]

active said:
If I understand you correctly this should not work or is just that the
4-byte items must be on 4-byte boundaries?

Or are the Shorts followed by 2 unused bytes?

The packing required by the target expecting the structure is defined by the
'#pragma pack' preprocessor directive. The general layout rule with 'pack'
is defined as follows (taken from the documentation on '#pragma pack'
contained in the latest MSDN shipment):

| The alignment of a member will be on a boundary that is either
| a multiple of n or a multiple of the size of the member, whichever
| is smaller.

So, what you have to do is checking the header files or the documentation
for information how the structure members should be laid out.

Most Win32 functions expect structure members of the structures they expect
to be laid out on 4-byte boundaries (following the rule above), but some
expect another packing, such as shell functions expecting 'SHFILEOPSTRUCT',
which must be packed with 'Pack:=1'.
 
A

active

Herfried K. Wagner said:
...
The packing required by the target expecting the structure is defined by
the '#pragma pack' preprocessor directive. The general layout rule with
'pack' is defined as follows (taken from the documentation on '#pragma
pack' contained in the latest MSDN shipment):

| The alignment of a member will be on a boundary that is either
| a multiple of n or a multiple of the size of the member, whichever
| is smaller.
...

Does vb.net treat packing the same way as C? That is, for a given n, will a
net structure be arranged the same way a C++ struct will be, given that they
contain a similar arangement of types?

I used items in your reply to search the Internet but I'm still not certian.

Seems to me the alignment statement above implies that a Structure (struct)
containg only 4 Bytes and a packing of 4 would be packed the same as if the
packing were 1; since the size of the member is 1 (which is smaller than 4)
it says the alignment would be 1.

But I'm pretty sure in that case Pack:=1 is required. Isn't it?

So I'm confused!


Thanks


It does explain that DWORD,WORD,WORD,DWORD and pack=4 would not have any
"holes" as I believe to be true.
Also for DWORD,WORD,BYTE,BYTE,DWORD
Please advise if that is incorrect!
 
H

Herfried K. Wagner [MVP]

active said:
Does vb.net treat packing the same way as C? That is, for a given n, will
a net structure be arranged the same way a C++ struct will be, given that
they contain a similar arangement of types?

Yes, I assume that the same rules are used. Unfortunately the documentation
is unclear about that.
Seems to me the alignment statement above implies that a Structure
(struct) containg only 4 Bytes and a packing of 4 would be packed the same
as if the packing were 1; since the size of the member is 1 (which is
smaller than 4) it says the alignment would be 1.

That's true. You can check it by instantiating a test structure and
determine its length using 'System.Runtime.InteropServices.Marshal.SizeOf'.
But I'm pretty sure in that case Pack:=1 is required. Isn't it?

No, it isn't for this simple scenario because the structure contains byte
members only.
It does explain that DWORD,WORD,WORD,DWORD and pack=4 would not have any
"holes" as I believe to be true.

That's true.
Also for DWORD,WORD,BYTE,BYTE,DWORD

That's true too. Both structures are 12 bytes long.
 
A

active

Thanks a lot

clears everything up


Herfried K. Wagner said:
Yes, I assume that the same rules are used. Unfortunately the
documentation is unclear about that.


That's true. You can check it by instantiating a test structure and
determine its length using
'System.Runtime.InteropServices.Marshal.SizeOf'.


No, it isn't for this simple scenario because the structure contains byte
members only.


That's true.


That's true too. Both structures are 12 bytes long.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top