gpt4 book ai didi

c# - 1 :1 Alignment of C# Structs with Streamed Delphi Records Possible?

转载 作者:太空宇宙 更新时间:2023-11-03 20:13:16 35 4
gpt4 key购买 nike

所以我有一个 Delphi 应用程序,它正在获取各种类型的记录,通过 stream.Write(record, sizeof(record)) 将它们扔到内存流中,然后通过命名管道发送它们。

拿这个 Delphi 记录:

Type TAboutData = record
Version : array[0..4] of Byte;
Build : Word;
BuildDate : TDateTime;
SVNChangeset : Word;
end;

当它通过命名管道发送时,它在一个 byte[] 数组中像这样出现:

长度:22 字节

0x06, 0x00, 0x00, 0x00, 4 bytes for array

0x00, 0x00, 0x00, 0x00, 2 bytes for build, 2 bytes for alignment?

0x15, 0xA3, 0x86, 0x3F, 8 bytes for double

0xBC, 0x44, 0xE4, 0x40,

0xA3, 0x02, 0x00, 0x00, 2 bytes for SVNChangeSet, 2 bytes alignment?

0x00, 0x00, 2 bytes for something else?

对齐问题

  1. 我认为这称为 4 字节边界对齐,对吗?
  2. 最后两个字节是做什么用的?

现在我正在尝试(未成功)将其编码为 C# 结构。

    [StructLayout(LayoutKind.Sequential)]
struct TAboutInfo
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
public byte[] Version;
public ushort Build;
public double BuildDate;
public ushort SVNChangeSet;
}

IntPtr ptr = Marshal.AllocHGlobal(bytebuffer.Length);
Marshal.Copy(ptr, bytebuffer, 0, bytebuffer.Length);
TAboutInfo ta = (TAboutInfo)Marshal.PtrToStructure(ptr, typeof(TAboutInfo));
Marshal.FreeHGlobal(ptr);

C# 问题

  1. 这根本行不通,而且我真的不知道如何解释对齐。我已经尝试过显式抵消,但效果不佳。
  2. 我有很多记录类型,有些记录类型的成员是其他记录的动态数组。我宁愿想出一个可靠的解决方案来将这些字节数组转换为结构或对象。

最佳答案

对齐通常被编译器用作优化。实际上每个结构都被填充为 4 的倍数(或者 8 我记不太清了)。

更新:我上面所说的对齐方式并不准确。阅读 David 的回答,了解有关编译器如何处理对齐记录的详细信息。维基百科文章包含一个合理的概述:http://en.wikipedia.org/wiki/Data_structure_alignment

无论如何,您可以使用 Pack 参数来指定对齐方式。 Pack 值为 1 返回结构的确切大小。

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]

关于数组,正确的用法是:

[MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)]
public char[] someCharArray;

当您从结构体转换为字节数组时,请注意该数组必须与声明的大小相匹配。在转换之前,如果内容较短,您应该使用 Array.Resize

struct.someCharArray = "Hello".ToCharArray();
Array.Resize<char>(ref struct.someCharArray, 20);

关于编码我使用这个方法从byte[]到结构:

    public static T ParseStructure<T>(byte[] array, int offset) where T : struct
{
if (array == null) throw new ArgumentNullException("array", "Input parameter cannot be null");

if (array.Length - offset < Marshal.SizeOf(typeof(T)))
Array.Resize<byte>(ref array, Marshal.SizeOf(typeof(T)) + offset);

int arraySize = array.Length - offset;
T returnItem;

// Allocate some unmanaged memory.
IntPtr buffer = Marshal.AllocHGlobal(arraySize);

// Copy the read byte array (byte[]) into the unmanaged memory block.
Marshal.Copy(array, offset, buffer, arraySize);

// Marshal the unmanaged memory block to a structure.
returnItem = (T)Marshal.PtrToStructure(buffer, typeof(T));

// Free the unmanaged memory block.
Marshal.FreeHGlobal(buffer);

return returnItem;
}

而这个方法恰恰相反:

    public static byte[] StructureToArray<T>(T structure) where T : struct
{
int objectSize = Marshal.SizeOf(structure);
byte[] result = new byte[objectSize];
IntPtr buffer = Marshal.AllocHGlobal(objectSize);

object dataStructure = (object)structure;

Marshal.StructureToPtr(dataStructure, buffer, true);

Marshal.Copy(buffer, result, 0, objectSize);
Marshal.FreeHGlobal(buffer);
return result;
}

另外,请使用以下代码检查框架计算的大小:

int objectSize = Marshal.SizeOf(structure);

终于找到了这个不错的article关于编码。

关于c# - 1 :1 Alignment of C# Structs with Streamed Delphi Records Possible?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18552777/

35 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com