Marshal Not Copying all Data to Fixed Byte Array

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • O.B.

    Marshal Not Copying all Data to Fixed Byte Array

    When using Marshal to copy data from a byte array to the structure
    below, only the first byte of the "other" array is getting copied from
    the original byte array. What do I need to specify to get
    Marshal.PtrToSt ructure to copy the all the data into the "other"
    array?


    [StructLayout(La youtKind.Explic it, Size = 40)]
    unsafe public struct DeadReckoning
    {
    [FieldOffset(0)]
    public byte algorithm; // 1 byte

    [FieldOffset(1)]
    public fixed byte other[15]; // 15 bytes

    [FieldOffset(16)]
    public Vector linearAccelerat ion; // 12 bytes

    [FieldOffset(28)]
    public Vector angularVelocity ; // 12 bytes
    }
    }

    // Given rawData as a byte array
    DeadReckoning dr = new DeadReckoning() ;
    IntPtr pData = Marshal.AllocHG lobal(40);
    Marshal.Copy(ra wData, 28, pData, 40);
    Marshal.PtrToSt ructure(pData, dr);
    Marshal.FreeHGl obal(pData);

    At this point, only dr.other[0] has the correct value; the values at
    1-14 indexes of dr.other are not set.

  • Jeroen Mostert

    #2
    Re: Marshal Not Copying all Data to Fixed Byte Array

    O.B. wrote:
    When using Marshal to copy data from a byte array to the structure
    below, only the first byte of the "other" array is getting copied from
    the original byte array. What do I need to specify to get
    Marshal.PtrToSt ructure to copy the all the data into the "other"
    array?
    >
    >
    [StructLayout(La youtKind.Explic it, Size = 40)]
    unsafe public struct DeadReckoning
    {
    [FieldOffset(0)]
    public byte algorithm; // 1 byte
    >
    [FieldOffset(1)]
    public fixed byte other[15]; // 15 bytes
    >
    [FieldOffset(16)]
    public Vector linearAccelerat ion; // 12 bytes
    >
    [FieldOffset(28)]
    public Vector angularVelocity ; // 12 bytes
    }
    }
    >
    What's "Vector"? A structure of 12 bytes?
    // Given rawData as a byte array
    DeadReckoning dr = new DeadReckoning() ;
    IntPtr pData = Marshal.AllocHG lobal(40);
    Marshal.Copy(ra wData, 28, pData, 40);
    Because you're using an unsafe struct with explicit layout, there's actually
    no need to use copying and marshalling at all. You can just write

    DeadReckoning dr;
    unsafe {
    fixed (byte* pData = &rawData[28]) {
    dr = *((DeadReckonin g*) pData);
    }
    }

    With this approach, however, you have to verify that "rawData" holds enough
    bytes to populate the structure, or it'll copy garbage from the stack. If
    you're lucky.
    Marshal.PtrToSt ructure(pData, dr);
    This shouldn't work, or at least, it doesn't for me. It throws
    ArgumentExcepti on because "dr" is a structure. This overload is for classes;
    for structures, the right syntax would be

    DeadReckoning dr = (DeadReckoning) Marshal.PtrToSt ructure(pData,
    typeof(DeadReck oning));

    --
    J.

    Comment

    • O.B.

      #3
      Re: Marshal Not Copying all Data to Fixed Byte Array

      On Jul 11, 3:40 pm, Jeroen Mostert <jmost...@xs4al l.nlwrote:
      O.B. wrote:
      When using Marshal to copy data from a byte array to the structure
      below, only the first byte of the "other" array is getting copied from
      the original byte array. What do I need to specify to get
      Marshal.PtrToSt ructure to copy the all the data into the "other"
      array?
      >
      [StructLayout(La youtKind.Explic it, Size = 40)]
      unsafe public struct DeadReckoning
      {
      [FieldOffset(0)]
      public byte algorithm; // 1 byte
      >
      [FieldOffset(1)]
      public fixed byte other[15]; // 15 bytes
      >
      [FieldOffset(16)]
      public Vector linearAccelerat ion; // 12 bytes
      >
      [FieldOffset(28)]
      public Vector angularVelocity ; // 12 bytes
      }
      }
      >
      What's "Vector"? A structure of 12 bytes?
      >
      // Given rawData as a byte array
      DeadReckoning dr = new DeadReckoning() ;
      IntPtr pData = Marshal.AllocHG lobal(40);
      Marshal.Copy(ra wData, 28, pData, 40);
      >
      Because you're using an unsafe struct with explicit layout, there's actually
      no need to use copying and marshalling at all. You can just write
      >
      DeadReckoning dr;
      unsafe {
      fixed (byte* pData = &rawData[28]) {
      dr = *((DeadReckonin g*) pData);
      }
      }
      >
      With this approach, however, you have to verify that "rawData" holds enough
      bytes to populate the structure, or it'll copy garbage from the stack. If
      you're lucky.
      >
      Marshal.PtrToSt ructure(pData, dr);
      >
      This shouldn't work, or at least, it doesn't for me. It throws
      ArgumentExcepti on because "dr" is a structure. This overload is for classes;
      for structures, the right syntax would be
      >
      DeadReckoning dr = (DeadReckoning) Marshal.PtrToSt ructure(pData,
      typeof(DeadReck oning));
      >
      --
      J.
      My bad. I was trying to trim down the post. The DeadReckoning
      structure is declared within a ExplicitLayout class (see below). The
      explicit constructor outlines the call to marshalling data from an
      array to the class structure.

      namespace DIS
      {
      [StructLayout(La youtKind.Explic it)]
      public class EntityState
      {
      [FieldOffset(0)]
      public Header header; // 12 bytes

      [FieldOffset(12)]
      public EntityIdentifie r entityID; // 6 bytes

      [FieldOffset(18)]
      public ForceIdentifier forceID; // 1 byte

      [FieldOffset(19)]
      public byte numArticulation s; // 1 byte

      [FieldOffset(20)]
      public EntityType type; // 8 bytes

      [FieldOffset(28)]
      public EntityType altType; // 8 bytes

      [FieldOffset(36)]
      public Vector linearVelocity; // 12 bytes

      [FieldOffset(48)]
      public WorldCoordinate location; // 24 bytes

      [FieldOffset(72)]
      public EulerAngles orientation; // 12 bytes

      [FieldOffset(84)]
      public Appearance appearance; // 4 bytes

      [FieldOffset(88)]
      public DeadReckoning deadReckoning = new DeadReckoning() ; //
      40 bytes

      [FieldOffset(128 )]
      public EntityMarking marking; // 12 bytes

      [FieldOffset(140 )]
      public Unsigned32 capabilities; // 4 bytes

      [MarshalAs(Unman agedType.ByValA rray, ArraySubType =
      UnmanagedType.S truct)]
      [FieldOffset(144 )]
      public Articulation[] articulations; // 16 bytes each

      public EntityState() { }

      public EntityState(byt e[] rawData)
      {
      // Copy the first 144 bytes to determine if there are
      articulations.
      unsafe
      {
      if (rawData.Length <= 144)
      {
      fixed (byte* pData = rawData)
      {
      Marshal.PtrToSt ructure((IntPtr ) pData, this);
      }
      }
      else
      {
      int dataSize = rawData.Length 144 ? 144 :
      rawData.Length;
      IntPtr pData = Marshal.AllocHG lobal(dataSize) ;
      Marshal.Copy(ra wData, 0, pData, dataSize);
      Marshal.PtrToSt ructure(pData, this); // Throws
      exception
      Marshal.FreeHGl obal(pData);
      }
      }

      // If there are articulations, allocate more memory for
      this class
      // and copy remaining data into articulations array.
      if (rawData.Length 144 && numArticulation s 0)
      {
      // Allocate memory for articulations
      articulations = new Articulation[numArticulation s];

      // Copy values for each articulation
      byte[] tempArray = new byte[16];
      for (int i = 0; i < numArticulation s; i++)
      {
      Array.Copy(rawD ata, 144 + i * 16, tempArray, 0,
      16);
      unsafe
      {
      fixed (byte* pData = tempArray)
      {
      articulations[i] =
      (Articulation)M arshal.PtrToStr ucture((IntPtr) pData,
      typeof(Articula tion));
      }
      }
      }
      }

      header.length = (ushort)rawData .Length;
      }

      public byte[] ToRaw()
      {
      int pduSize = (int) header.length;
      byte[] byteArray = new byte[pduSize];
      IntPtr pointer = Marshal.AllocHG lobal(pduSize);
      Marshal.Structu reToPtr(this, pointer, false);
      Marshal.Copy(po inter, byteArray, 0, pduSize);
      Marshal.FreeHGl obal(pointer);
      return byteArray;
      }
      }
      }

      Comment

      Working...