By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
457,915 Members | 1,362 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 457,915 IT Pros & Developers. It's quick & easy.

Structure alignment struggle.

P: n/a
Hi all.
I've got the following code as a part of managed C++ library that is
loaded by a project in C#:

public ref class FlyCaptureEnumsAndStructsManaged
{
public:
typedef enum class FlyCaptureCameraModel { blabla, blabla2 };
typedef enum class FlyCaptureCameraType { blabla, blablabla, blamax =
0x7FFFFFFF };

[StructLayout(LayoutKind::Explicit, Pack=1 Size=2028)]
typedef ref struct FlyCaptureInfoEx
{
[FieldOffset(0)] int SerialNumber;
[FieldOffset(4)] FlyCaptureCameraType CameraType;
[FieldOffset(8)] FlyCaptureCameraModel CameraModel;
[FieldOffset(12), MarshalAs(UnmanagedType::ByValTStr, SizeConst=512)]
String^ pszModelName;

... blablabla
};
};

Now, I'm facing some alignment issue after this has been ported to x64
platform. I used to work with windows x86 and VS 2005, now am working
with VS 2008 and XP x64.

It looks that the offset FieldOffset(12) is for some reason treated as
an inappropriate layout as raised exceptions indicate this clearly. When
It definitely helps when I amend the offset position to FieldOffset(16).
I'm a bit puzzled cos I've tried to force alignment with Pack=1 and
Pack=4, though it still acts like it was specified Pack=8.

Just to stress out as well that the same structure built directly in C#
(even without specifying the pack size) seems to have the desired 4 byte
layout.
Do you have any clue what is going on here? Perhaps this all is down to
some compiler switches?
Thanks a lot,
Peter.
Jun 27 '08 #1
Share this Question
Share on Google+
9 Replies


P: n/a
It would have helped a lot more if you hadn't removed part of the struct
definition.

I'm having a bit of trouble understanding why you're explicitly defining the
field offsets for the types involved. You've manually specified the
locations where they would be at normally simply using a sequential layout,
but I can't tell for sure since you decided to partially show us the struct.

Also according to the docs (unless I'm interpreting them incorrectly), the
pack property only works when you've specified Sequential for the layout.
http://msdn.microsoft.com/en-us/libr...bute.pack.aspx

What you've shown us the equivalent of: I have a problem with this method,
it's throwing an object null reference exception. Why?
void DoSomething() {
int x = 0;
...
}

"A n g l e r" <p|*************@h-o-t-m-a-i-l.c_o_mwrote in message
news:g3**********@news.onet.pl...
Hi all.
I've got the following code as a part of managed C++ library that is
loaded by a project in C#:

public ref class FlyCaptureEnumsAndStructsManaged
{
public:
typedef enum class FlyCaptureCameraModel { blabla, blabla2 };
typedef enum class FlyCaptureCameraType { blabla, blablabla, blamax =
0x7FFFFFFF };

[StructLayout(LayoutKind::Explicit, Pack=1 Size=2028)]
typedef ref struct FlyCaptureInfoEx
{
[FieldOffset(0)] int SerialNumber;
[FieldOffset(4)] FlyCaptureCameraType CameraType;
[FieldOffset(8)] FlyCaptureCameraModel CameraModel; [FieldOffset(12),
MarshalAs(UnmanagedType::ByValTStr, SizeConst=512)] String^ pszModelName;

... blablabla
};
};

Now, I'm facing some alignment issue after this has been ported to x64
platform. I used to work with windows x86 and VS 2005, now am working with
VS 2008 and XP x64.

It looks that the offset FieldOffset(12) is for some reason treated as an
inappropriate layout as raised exceptions indicate this clearly. When It
definitely helps when I amend the offset position to FieldOffset(16). I'm
a bit puzzled cos I've tried to force alignment with Pack=1 and Pack=4,
though it still acts like it was specified Pack=8.

Just to stress out as well that the same structure built directly in C#
(even without specifying the pack size) seems to have the desired 4 byte
layout.
Do you have any clue what is going on here? Perhaps this all is down to
some compiler switches?
Thanks a lot,
Peter.
Jun 27 '08 #2

P: n/a
A n g l e r wrote:
Hi all.
I've got the following code as a part of managed C++ library that is
loaded by a project in C#:

public ref class FlyCaptureEnumsAndStructsManaged
{
public:
typedef enum class FlyCaptureCameraModel { blabla, blabla2 };
typedef enum class FlyCaptureCameraType { blabla, blablabla, blamax
= 0x7FFFFFFF };

[StructLayout(LayoutKind::Explicit, Pack=1 Size=2028)]
typedef ref struct FlyCaptureInfoEx
{
[FieldOffset(0)] int SerialNumber;
[FieldOffset(4)] FlyCaptureCameraType CameraType;
[FieldOffset(8)] FlyCaptureCameraModel CameraModel;
[FieldOffset(12), MarshalAs(UnmanagedType::ByValTStr,
SizeConst=512)] String^ pszModelName;
What do you have here? What is the FielfOffset of the next member?

In x64, the pointers are 8 bytes instead of 4 bytes. If you have placed
the next member at 16, the pointer would overlap it.
... blablabla
};
};

Now, I'm facing some alignment issue after this has been ported to x64
platform. I used to work with windows x86 and VS 2005, now am working
with VS 2008 and XP x64.

It looks that the offset FieldOffset(12) is for some reason treated as
an inappropriate layout as raised exceptions indicate this clearly. When
It definitely helps when I amend the offset position to FieldOffset(16).
I'm a bit puzzled cos I've tried to force alignment with Pack=1 and
Pack=4, though it still acts like it was specified Pack=8.

Just to stress out as well that the same structure built directly in C#
(even without specifying the pack size) seems to have the desired 4 byte
layout.
Do you have any clue what is going on here? Perhaps this all is down to
some compiler switches?
Thanks a lot,
Peter.

--
Göran Andersson
_____
http://www.guffa.com
Jun 27 '08 #3

P: n/a
I'm having a bit of trouble understanding why you're explicitly defining
the field offsets for the types involved. You've manually specified the
locations where they would be at normally simply using a sequential
layout, but I can't tell for sure since you decided to partially show us
the struct.
Well, I've just replaced this all with Sequential and now it turns out
to work fine. The reason why I have it declared likewise is that
Sequential layout didn't seem to work fine on my previous machine and VS
2005 :d I have no clue what was the reason.
Also according to the docs (unless I'm interpreting them incorrectly),
the pack property only works when you've specified Sequential for the
layout.
http://msdn.microsoft.com/en-us/libr...bute.pack.aspx
Yep, you're right. I've also spotted this. Any reason why Explicit
layout doesn't work as aligned every 4 bytes on x64?

Thanks,
Peter
Jun 27 '08 #4

P: n/a
What do you have here? What is the FielfOffset of the next member?

In x64, the pointers are 8 bytes instead of 4 bytes. If you have placed
the next member at 16, the pointer would overlap it.

Erm, first three fields aren't pointers. The forth one has to do with
pointers, though I don't get why it needs to be aligned every 8 bytes
unless it's actual position is calculated with respect to the end of the
structure rather than the beginning. Perhaps I misapprehend some aspects
of this sort of layout, though Sequential doesn't force me to have 8
bytes alignment and works fine ... So, what is the little trick in it?

Cheers,
Peter.
Jun 27 '08 #5

P: n/a
Explictly defining the layout for members of structures determine where in
the structs the members get serialized based on the position from the start
of the struct. Also, FYI, you don't need to specify sequential for the
layout since it's the default setting for structs.

[StructLayout(LayoutKind.Explicit)]
struct MyStruct {
[FieldOffset(0)]
public int A;

[FieldOffset(4)]
public int B;

[FieldOffset(8)]
public IntPtr C;

[FieldOffset(12)]
public int D;
}

The Int32 type is 4 bytes wide, which is why the offset is 4 bytes apart.
However, since the C member is a pointer - on a 32 bit system this would be
4 bytes wide, whereas on a 64 bit system it is 8 bytes wide. So, if you're
explicitly defining the field positions and you move the application to a 64
bit system you can see that D would be in the wrong position as it would
actually need to be at offset 16.

Glad you got everything working. Happy to help :)

"A n g l e r" <p|*************@h-o-t-m-a-i-l.c_o_mwrote in message
news:g3**********@news.onet.pl...
>
>What do you have here? What is the FielfOffset of the next member?

In x64, the pointers are 8 bytes instead of 4 bytes. If you have placed
the next member at 16, the pointer would overlap it.


Erm, first three fields aren't pointers. The forth one has to do with
pointers, though I don't get why it needs to be aligned every 8 bytes
unless it's actual position is calculated with respect to the end of the
structure rather than the beginning. Perhaps I misapprehend some aspects
of this sort of layout, though Sequential doesn't force me to have 8 bytes
alignment and works fine ... So, what is the little trick in it?

Cheers,
Peter.
Jun 27 '08 #6

P: n/a
Jeff, yes, though this still doesn't answer my question which is why
Sequential offset doesn't require such alignment? What is the actual
difference in representing both types of structures on a system level?

Cheers,
P.
Explictly defining the layout for members of structures determine where
in the structs the members get serialized based on the position from the
start of the struct. Also, FYI, you don't need to specify sequential for
the layout since it's the default setting for structs.

[StructLayout(LayoutKind.Explicit)]
struct MyStruct {
[FieldOffset(0)]
public int A;

[FieldOffset(4)]
public int B;

[FieldOffset(8)]
public IntPtr C;

[FieldOffset(12)]
public int D;
}

The Int32 type is 4 bytes wide, which is why the offset is 4 bytes
apart. However, since the C member is a pointer - on a 32 bit system
this would be 4 bytes wide, whereas on a 64 bit system it is 8 bytes
wide. So, if you're explicitly defining the field positions and you move
the application to a 64 bit system you can see that D would be in the
wrong position as it would actually need to be at offset 16.
Jun 27 '08 #7

P: n/a
A n g l e r wrote:
>
>What do you have here? What is the FielfOffset of the next member?

In x64, the pointers are 8 bytes instead of 4 bytes. If you have
placed the next member at 16, the pointer would overlap it.


Erm, first three fields aren't pointers. The forth one has to do with
pointers, though I don't get why it needs to be aligned every 8 bytes
unless it's actual position is calculated with respect to the end of the
structure rather than the beginning. Perhaps I misapprehend some aspects
of this sort of layout, though Sequential doesn't force me to have 8
bytes alignment and works fine ... So, what is the little trick in it?

Cheers,
Peter.
The third member isn't a pointer? I don't do any development in C++
these days, so I don't know exactly what the types translates into...

You are mixing layout attributes with marshalling attributes, perhaps
that's the problem? Layout attributes are used by the CLR to layout the
managed data, while marshalling attributes are used by the marshalling
methods when the data is copied into an unmanaged data structure.

--
Göran Andersson
_____
http://www.guffa.com
Jun 27 '08 #8

P: n/a
The third member isn't a pointer? I don't do any development in C++
these days, so I don't know exactly what the types translates into...
The forth one from my example is pointer - at least as long as I'm of a
sound mind ;)
You are mixing layout attributes with marshalling attributes, perhaps
that's the problem? Layout attributes are used by the CLR to layout the
managed data, while marshalling attributes are used by the marshalling
methods when the data is copied into an unmanaged data structure.
Erm, ok, though this seems to be a sleek way of passing unmanaged
structure with strings to C# environment ...
Jun 27 '08 #9

P: n/a
There is no difference in the structure itself, the difference is how the
marshaller handles the struct. When the members are laid out sequentially
(LayoutKind.Sequential) you're telling .NET to handle the marshalling for
you for that struct. It will determine where the members need to go when
it's marshalling them back and forth. If you're using an explicit layout
with field offsets for the members, you're telling the marshaller where it
should look for the data.

This would be what the struct looks like on a 32 bit system.

A B C D
00 00 00 00 | 00 00 00 00 | 00 00 00 00 | 00 00 00 00
0 4 8 12

And this would be the same struct represented on a 64 bit system.

A B C
D
00 00 00 00 | 00 00 00 00 | 00 00 00 00 00 00 00 00 | 00 00 00 00
0 4 8 -12-
16

With the example I wrote earlier, it's basically telling the marshaller to
look for the D field at position 12 of the array, which would be the last 4
bytes of the pointer used by the C field. I've rarely needed to use an
explicit layout for a struct. If I remember the last time I needed one I was
having to store 2 different objects at the same position within the struct.
Probably was from a union inside the struct defintion I was using in the
Win32 API.

Generally speaking you shouldn't use explicit layouts unless you absolutely
have to. They can cause a lot of problems when using different platforms.

"A n g l e r" <p|*************@h-o-t-m-a-i-l.c_o_mwrote in message
news:g3**********@news.onet.pl...
Jeff, yes, though this still doesn't answer my question which is why
Sequential offset doesn't require such alignment? What is the actual
difference in representing both types of structures on a system level?

Cheers,
P.
>Explictly defining the layout for members of structures determine where
in the structs the members get serialized based on the position from the
start of the struct. Also, FYI, you don't need to specify sequential for
the layout since it's the default setting for structs.

[StructLayout(LayoutKind.Explicit)]
struct MyStruct {
[FieldOffset(0)]
public int A;

[FieldOffset(4)]
public int B;

[FieldOffset(8)]
public IntPtr C;

[FieldOffset(12)]
public int D;
}

The Int32 type is 4 bytes wide, which is why the offset is 4 bytes apart.
However, since the C member is a pointer - on a 32 bit system this would
be 4 bytes wide, whereas on a 64 bit system it is 8 bytes wide. So, if
you're explicitly defining the field positions and you move the
application to a 64 bit system you can see that D would be in the wrong
position as it would actually need to be at offset 16.
Jun 27 '08 #10

This discussion thread is closed

Replies have been disabled for this discussion.