Marshal 中 space 末尾的数据对齐

Alignment of data on the end side of space in Marshal

我有以下结构:

[StructLayout(LayoutKind.Sequential)]
public struct mystructure
{
    public Byte fieldA;
    public Byte fieldB;
    public UInt16 fieldC;
    public UInt32 fieldD;
}

然后,填充数据:

var obj = new mystructure()
{
    fieldA = 4
    ,
    fieldB = 0
    ,
    fieldC = 16
    ,
    fieldD = 9
};

和编组:

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);

我在 ret 变量中得到了这个数据布局:

[0]: 4
[1]: 0
[2]: 16
[3]: 0
[4]: 9
[5]: 0
[6]: 0
[7]: 0

所有数据都在你的开头对齐space,我如何在结尾对齐?请注意,它不同于使用 [FieldOffset] 属性。 我需要以下结果:

[0]: 4
[1]: 0
[2]: 0
[3]: 16
[4]: 0
[5]: 0
[6]: 0
[7]: 9

已更新 - 我的解决方案

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
                        )
                );
        }
    }
}

您的问题是关于字节顺序而不是对齐。字节顺序或 endianness 是关于最重要的字节是第一个还是最后一个。

Marshal.StructurePtr 使用底层的字节顺序 CPU 因为它假定您要调用非托管函数。

这可能对你有帮助Marshalling a big-endian byte collection into a struct in order to pull out values

基本上您必须手动创建字节数组。大端也称为 network byte order。您可以使用 ipaddress.hosttonetworkorder 获取整数和长整数的正确格式。