如何将byte []分配给记录

时间:2009-05-18 17:39:26

标签: delphi

在C ++中它就是这样做的:

tPacket * packet = (tPacket *)data; //data is byte[] array; tPacket is a structure

在C#中:

tPacket t = new tPacket();
GCHandle pin = GCHandle.Alloc(data, GCHandleType.Pinned);
t = (tPacket)Marshal.PtrToStructure(pin.AddrOfPinnedObject(), typeof(tPacket));
pin.free();

数据是在通过TCP接收数据包后用作接收缓冲区的字节数组。该代码将数据放入tPacket(结构)的实例中,以便稍后可以访问该结构。

如何在Delphi中完成?

3 个答案:

答案 0 :(得分:4)

您还可以使用absolute关键字强制两个结构共享相同的内存地址:

var
  Data: array[1..SizeOf(TMyStruct)] of byte;
  s : TMyStruct absolute Data;

写入S的任何数据也可作为数据使用,无需执行移动或指针转换。

答案 1 :(得分:3)

你可以在Delphi中完全按照C ++的方式做。但是,为记录指针定义命名类型,因为Delphi不允许您在语句中定义类型。

type
  PPacket = ^TPacket;
var
  packet: PPacket;

packet := PPacket(@data[0]);
  • 我使用@data[0]的原因是,无论数据是否为动态数组,它都能正常工作。如果它是一个动态数组,那么data实际上是指向数据包第一个字节的指针,所以这可行:

    packet := PPacket(data); // for dynamic array only
    

    但如果data 不是动态数组,那么该类型转换将无效。您需要将指针类型转换为data,如下所示:

    packet := PPacket(@data); // for static array only
    

    如果它是动态数组,那将无效。第一个代码适用于这两种情况。但是如果你启用了范围检查(并且你可能应该),那么我认为如果data是一个零长度的动态数组,第一个代码将引发异常,所以要小心。


如果你想改为使用C#路由,那么你将数组中的字节复制到一个单独的TPacket变量中,那么我将使用它:

var
  packet: TPacket;

// Source param comes first. Params are passed by
// reference automatically.
Move(data[0], packet, SizeOf(packet));

您需要确保data包含足够的字节来填充整个TPacket值。 TPacket最好不要包含任何编译器管理的类型,例如stringVariantIUnknown或动态数组类型。在这种情况下,指针类型转换和Move都不能表现良好。

答案 2 :(得分:2)

这可能很棘手,因为您必须确保源和目标结构布局相同。如果是,那么你有2个选择,要么使用指向数组的指针,要么使用内存副本:

指针:

type
  // Declare a pointer type for your struct.
  PMyStruct = TMyStruct^;

...

var
  ptr: PMyStruct;
begin
  ptr := PMyStruct(Cardinal(@Data));
  // use ptr...
end;

记忆复制:

var
  Data: array of Byte;
  s: TMyStruct;
begin
  // fill Data...
  if SizeOf(s) <> Length(Data) then
    raise Exception.Create('Input size is not the same size as destination structure.');
  CopyMemory(@s, @Data, Length(Data));
  // use s...
end;