.NET Framework Developer Center >
.NET Development Forums
>
Common Language Runtime
>
Marshal Structure
Marshal Structure
- I have an unmanaged structure :
struct {
int level;
char user[5];
char name[32];
...
}
that I'm attempting to marshal into managed structure:
[StructLayout(LayoutKind.Explicit, CharSet=CharSet.Ansi,Pack=1)]
public struct giidbm_MddDefinition
{
[MarshalAs(UnmanagedType.I4),FieldOffset(0)]
public int level;
[MarshalAs(UnamangedType.LPStr,SizeConst=4,FieldOffset(4)]
public string user;
[MarshalAs(UnmanagedType.LPStr,SizeConst=31,FieldOffset(9)]
public string name;
...
}
This bombs at every instantiation of giidbm_MddDefinition, saying that:
Message="Could not load type 'giidbm_MddDefinition' from assembly 'ConsoleApplication1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' because it contains an object field at offset 9 that is incorrectly aligned or overlapped by a non-object field."
I've tried many different ways to marshal this, but I always end up with the above error.
What am I missing?
Answers
- Hello Jim
Please try this declaration:
[System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential, CharSet=System.Runtime.InteropServices.CharSet.Ansi)]
public struct giidbm_MddDefinition {
/// int
public int level;
/// char[5]
[System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.ByValTStr, SizeConst=5)]
public string user;
/// char[32]
[System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.ByValTStr, SizeConst=32)]
public string name;
}
It was auto-generated by one of my favorite tools: P/Invoke Interop Assistant
http://blogs.msdn.com/bclteam/archive/2008/06/23/p-invoke-interop-assistant-justin-van-patten.aspx
Regards,
Jialiang Ge
MSDN Subscriber Support in Forum
If you have any feedback of our support, please contact msdnmg@microsoft.com.
Please remember to mark the replies as answers if they help and unmark them if they provide no help.
Welcome to the All-In-One Code Framework! If you have any feedback, please tell us.- Marked As Answer byJialiang Ge [MSFT]MSFT, ModeratorFriday, November 13, 2009 6:17 AM
I have an unmanaged structure :
struct {
int level;
char user[5];
char name[32];
...
}
that I'm attempting to marshal into managed structure:
[StructLayout(LayoutKind.Explicit, CharSet=CharSet.Ansi,Pack=1)]
public struct giidbm_MddDefinition
{
[MarshalAs(UnmanagedType.I4),FieldOffset(0)]
public int level;
[MarshalAs(UnamangedType.LPStr,SizeConst=4,FieldOffset(4)]
public string user;
[MarshalAs(UnmanagedType.LPStr,SizeConst=31,FieldOffset(9)]
public string name;
...
}
This bombs at every instantiation of giidbm_MddDefinition, saying that:
Message="Could not load type 'giidbm_MddDefinition' from assembly 'ConsoleApplication1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' because it contains an object field at offset 9 that is incorrectly aligned or overlapped by a non-object field."
I've tried many different ways to marshal this, but I always end up with the above error.
What am I missing?
You can actually avoid marshalling here, if you are prepared to use 'unsafe' C# features:
public unsafe struct giidbm_MddDefintion
{
public int level;
public fixed byte user[5];
public fixed byte name[32];
}
This is an example of a blittable struct, meaning its physical organization is identical in managed and unmanaged code and the marshaller has very little work to do.
To aid in manipulating the strings, you could add some properties:
public unsafe struct giidbm_MddDefintion
{
public int level;
private fixed byte user[5];
private fixed byte name[32];
// Treate the fixed byte buffer as a 'String'
public string User
{
get { }
set { }
}
// Treate the fixed byte buffer as a 'String'
public string Name
{
get { }
set { }
}
}
This may or may not help you with your specific need, bit it is worth knowing about this technique sometimes and can be fast, for example you can readily pass such a struct by reference (or via a pointer) directly into unmanaged code.
Cap'n- Edited byCaptain Kernel Monday, November 02, 2009 9:07 PMclarify
- Edited byCaptain Kernel Monday, November 02, 2009 9:09 PMpointers
- Edited byCaptain Kernel Monday, November 02, 2009 9:08 PMtidyup
- Marked As Answer byJialiang Ge [MSFT]MSFT, ModeratorFriday, November 13, 2009 6:17 AM
All Replies
- Try this:
[StructLayout(LayoutKind.Explicit, CharSet = CharSet.Ansi, Pack = 1)]
public struct giidbm_MddDefinition
{
[MarshalAs(UnmanagedType.I4), FieldOffset(0)]
public int level;
[MarshalAs(UnmanagedType.LPStr, SizeConst = 4), FieldOffset(4)]
public string user;
[MarshalAs(UnmanagedType.LPStr, SizeConst = 31), FieldOffset(8)]
public string name;
}
If you really need name to start at offset 9, take a look at this: http://stackoverflow.com/questions/1190079/incorrectly-aligned-or-overlapped-by-a-non-object-field-error - Beware that the structure alignment requested with the [StructLayout] attribute is honored both in managed code as well as for P/Invoke marshaling. That's a problem here, a reference type like string must be aligned on an address that's a multiple of 4. Just omit the FieldOffset attributes and use LayoutKind.Sequential. The P/Invoke marshaller will align the unmanaged version of the struct as you want it.
Note that your SizeConst values are wrong, it must include the terminating 0. Make them one higher.
Hans Passant. - Hello Jim
Please try this declaration:
[System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential, CharSet=System.Runtime.InteropServices.CharSet.Ansi)]
public struct giidbm_MddDefinition {
/// int
public int level;
/// char[5]
[System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.ByValTStr, SizeConst=5)]
public string user;
/// char[32]
[System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.ByValTStr, SizeConst=32)]
public string name;
}
It was auto-generated by one of my favorite tools: P/Invoke Interop Assistant
http://blogs.msdn.com/bclteam/archive/2008/06/23/p-invoke-interop-assistant-justin-van-patten.aspx
Regards,
Jialiang Ge
MSDN Subscriber Support in Forum
If you have any feedback of our support, please contact msdnmg@microsoft.com.
Please remember to mark the replies as answers if they help and unmark them if they provide no help.
Welcome to the All-In-One Code Framework! If you have any feedback, please tell us.- Marked As Answer byJialiang Ge [MSFT]MSFT, ModeratorFriday, November 13, 2009 6:17 AM
- Hello Jim
How are you? I'm writing to check the status of the issue on your side. If you have any questions, please feel free to post here.
Regards,
Jialiang Ge
MSDN Subscriber Support in Forum
If you have any feedback of our support, please contact msdnmg@microsoft.com.
Please remember to mark the replies as answers if they help and unmark them if they provide no help.
Welcome to the All-In-One Code Framework! If you have any feedback, please tell us. I have an unmanaged structure :
struct {
int level;
char user[5];
char name[32];
...
}
that I'm attempting to marshal into managed structure:
[StructLayout(LayoutKind.Explicit, CharSet=CharSet.Ansi,Pack=1)]
public struct giidbm_MddDefinition
{
[MarshalAs(UnmanagedType.I4),FieldOffset(0)]
public int level;
[MarshalAs(UnamangedType.LPStr,SizeConst=4,FieldOffset(4)]
public string user;
[MarshalAs(UnmanagedType.LPStr,SizeConst=31,FieldOffset(9)]
public string name;
...
}
This bombs at every instantiation of giidbm_MddDefinition, saying that:
Message="Could not load type 'giidbm_MddDefinition' from assembly 'ConsoleApplication1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' because it contains an object field at offset 9 that is incorrectly aligned or overlapped by a non-object field."
I've tried many different ways to marshal this, but I always end up with the above error.
What am I missing?
You can actually avoid marshalling here, if you are prepared to use 'unsafe' C# features:
public unsafe struct giidbm_MddDefintion
{
public int level;
public fixed byte user[5];
public fixed byte name[32];
}
This is an example of a blittable struct, meaning its physical organization is identical in managed and unmanaged code and the marshaller has very little work to do.
To aid in manipulating the strings, you could add some properties:
public unsafe struct giidbm_MddDefintion
{
public int level;
private fixed byte user[5];
private fixed byte name[32];
// Treate the fixed byte buffer as a 'String'
public string User
{
get { }
set { }
}
// Treate the fixed byte buffer as a 'String'
public string Name
{
get { }
set { }
}
}
This may or may not help you with your specific need, bit it is worth knowing about this technique sometimes and can be fast, for example you can readily pass such a struct by reference (or via a pointer) directly into unmanaged code.
Cap'n- Edited byCaptain Kernel Monday, November 02, 2009 9:07 PMclarify
- Edited byCaptain Kernel Monday, November 02, 2009 9:09 PMpointers
- Edited byCaptain Kernel Monday, November 02, 2009 9:08 PMtidyup
- Marked As Answer byJialiang Ge [MSFT]MSFT, ModeratorFriday, November 13, 2009 6:17 AM
- Thanks Captain!
Hello Jim, many community friends have shared their ideas in this thread. Could you please check them out? If you have any other questions, please feel free to post here.
Regards,
Jialiang Ge
MSDN Subscriber Support in Forum
If you have any feedback of our support, please contact msdnmg@microsoft.com.
Please remember to mark the replies as answers if they help and unmark them if they provide no help.
Welcome to the All-In-One Code Framework! If you have any feedback, please tell us.


