Marshal Not Copying all Data to Fixed Byte Array

O

O.B.

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.PtrToStructure to copy the all the data into the "other"
array?


[StructLayout(LayoutKind.Explicit, 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 linearAcceleration; // 12 bytes

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

// Given rawData as a byte array
DeadReckoning dr = new DeadReckoning();
IntPtr pData = Marshal.AllocHGlobal(40);
Marshal.Copy(rawData, 28, pData, 40);
Marshal.PtrToStructure(pData, dr);
Marshal.FreeHGlobal(pData);

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

Jeroen Mostert

O.B. said:
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.PtrToStructure to copy the all the data into the "other"
array?


[StructLayout(LayoutKind.Explicit, 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 linearAcceleration; // 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.AllocHGlobal(40);
Marshal.Copy(rawData, 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 = *((DeadReckoning*) 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.PtrToStructure(pData, dr);

This shouldn't work, or at least, it doesn't for me. It throws
ArgumentException because "dr" is a structure. This overload is for classes;
for structures, the right syntax would be

DeadReckoning dr = (DeadReckoning) Marshal.PtrToStructure(pData,
typeof(DeadReckoning));
 
O

O.B.

O.B. said:
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.PtrToStructure to copy the all the data into the "other"
array?
[StructLayout(LayoutKind.Explicit, 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 linearAcceleration; // 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.AllocHGlobal(40);
Marshal.Copy(rawData, 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 = *((DeadReckoning*) 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.PtrToStructure(pData, dr);

This shouldn't work, or at least, it doesn't for me. It throws
ArgumentException because "dr" is a structure. This overload is for classes;
for structures, the right syntax would be

DeadReckoning dr = (DeadReckoning) Marshal.PtrToStructure(pData,
typeof(DeadReckoning));

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(LayoutKind.Explicit)]
public class EntityState
{
[FieldOffset(0)]
public Header header; // 12 bytes

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

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

[FieldOffset(19)]
public byte numArticulations; // 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(UnmanagedType.ByValArray, ArraySubType =
UnmanagedType.Struct)]
[FieldOffset(144)]
public Articulation[] articulations; // 16 bytes each

public EntityState() { }

public EntityState(byte[] rawData)
{
// Copy the first 144 bytes to determine if there are
articulations.
unsafe
{
if (rawData.Length <= 144)
{
fixed (byte* pData = rawData)
{
Marshal.PtrToStructure((IntPtr) pData, this);
}
}
else
{
int dataSize = rawData.Length > 144 ? 144 :
rawData.Length;
IntPtr pData = Marshal.AllocHGlobal(dataSize);
Marshal.Copy(rawData, 0, pData, dataSize);
Marshal.PtrToStructure(pData, this); // Throws
exception
Marshal.FreeHGlobal(pData);
}
}

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

// Copy values for each articulation
byte[] tempArray = new byte[16];
for (int i = 0; i < numArticulations; i++)
{
Array.Copy(rawData, 144 + i * 16, tempArray, 0,
16);
unsafe
{
fixed (byte* pData = tempArray)
{
articulations =
(Articulation)Marshal.PtrToStructure((IntPtr)pData,
typeof(Articulation));
}
}
}
}

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

public byte[] ToRaw()
{
int pduSize = (int) header.length;
byte[] byteArray = new byte[pduSize];
IntPtr pointer = Marshal.AllocHGlobal(pduSize);
Marshal.StructureToPtr(this, pointer, false);
Marshal.Copy(pointer, byteArray, 0, pduSize);
Marshal.FreeHGlobal(pointer);
return byteArray;
}
}
}
 

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