I have the flollowing structure:
[StructLayout(LayoutKind.Sequential)]
public struct mystructure
{
public Byte fieldA;
public Byte fieldB;
public UInt16 fieldC;
public UInt32 fieldD;
}
Then, filling with data:
var obj = new mystructure()
{
fieldA = 4
,
fieldB = 0
,
fieldC = 16
,
fieldD = 9
};
And marshaling:
Int32 objsize = Marshal.SizeOf(typeof(mystructure));
Byte[] ret = new Byte[objsize];
IntPtr buff = Marshal.AllocHGlobal(objsize);
Marshal.StructureToPtr(obj, buff, true);
Marshal.Copy(buff, ret, 0, objsize);
Marshal.FreeHGlobal(buff);
I got this data layout in my ret
variable:
[0]: 4
[1]: 0
[2]: 16
[3]: 0
[4]: 9
[5]: 0
[6]: 0
[7]: 0
All data are aligned at the beginning of your space, how do I align on the end? Note that it is different from using the [FieldOffset]
atribute.
I need the following result:
[0]: 4
[1]: 0
[2]: 0
[3]: 16
[4]: 0
[5]: 0
[6]: 0
[7]: 9
UPDATED - My solution
public static void LittleEndianToBigEndian<T>(Byte[] data, Int32 startOffset = 0) where T : struct
{
LittleEndianToBigEndian(typeof(T), data, startOffset);
}
public static void LittleEndianToBigEndian(Type structType, Byte[] data, Int32 startOffset = 0)
{
if (!structType.IsValueType || structType.IsEnum || structType.IsPrimitive)
throw new ArgumentException("The conversion only supports struct types", "structType");
var validFieldsRule = new Func<FieldInfo, Boolean>(f =>
!f.IsStatic &&
f.FieldType != typeof(String) &&
f.FieldType != typeof(Byte) &&
f.FieldType != typeof(SByte) &&
(f.FieldType.IsArray || f.FieldType.IsValueType)
);
foreach (var field in structType.GetFields().Where(validFieldsRule))
{
var offset = Marshal.OffsetOf(structType, field.Name).ToInt32();
var effectiveOffset = startOffset + offset;
if (field.FieldType.GetFields().Any(validFieldsRule) && !field.FieldType.IsEnum)
{
LittleEndianToBigEndian(field.FieldType, data, effectiveOffset);
}
else if (field.FieldType.IsArray)
{
//to-do: deal with arrays!
}
else
{
Array.Reverse
(
data
,
effectiveOffset
,
Marshal.SizeOf
(
field.FieldType.IsEnum ?
Enum.GetUnderlyingType(field.FieldType)
:
field.FieldType
)
);
}
}
}