在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中完成?
答案 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
最好不要包含任何编译器管理的类型,例如string
,Variant
,IUnknown
或动态数组类型。在这种情况下,指针类型转换和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;