none
Marshal Structure RRS feed

  • Question

  • 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?
    Monday, October 26, 2009 1:47 PM

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.
    Tuesday, October 27, 2009 8:50 AM
    Moderator
  • 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


    Monday, November 2, 2009 9:06 PM

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
    Monday, October 26, 2009 3:43 PM
  • 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.
    Monday, October 26, 2009 10:37 PM
    Moderator
  • 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.
    Tuesday, October 27, 2009 8:50 AM
    Moderator
  • 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.
    Monday, November 2, 2009 3:08 AM
    Moderator
  • 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


    Monday, November 2, 2009 9:06 PM
  • 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.
    Friday, November 6, 2009 6:22 AM
    Moderator