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

Marshal Not Copying all Data to Fixed Byte Array

P: n/a
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.

Jul 11 '08 #1
Share this Question
Share on Google+
2 Replies


P: n/a
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.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));

--
J.
Jul 11 '08 #2

P: n/a
On Jul 11, 3:40 pm, Jeroen Mostert <jmost...@xs4all.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.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));

--
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(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[i] =
(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;
}
}
}

Jul 11 '08 #3

This discussion thread is closed

Replies have been disabled for this discussion.