如何从TBytes数组访问DWORD?

时间:2017-07-24 22:34:10

标签: arrays delphi casting

我有一个TBytes数组,我希望像DWORD数组一样访问它,但我不想制作TBytes数组的新副本。我试图对它进行类型转换,但新变量的长度与旧变量的长度相同,而不是Length(TBytes)/4。如果我想设置正确的长度,Delphi会复制它,两个数组之间的连接就会丢失。它可以使它工作吗?

2 个答案:

答案 0 :(得分:3)

您需要获取指向数组数据的指针,然后键入它。简单地键入指针并不会改变你仍然指向一个字节数组的事实,这就是为什么长度是相同的。您必须通过将数组长度除以4来手动计算DWORD的数量。

试试这个:

var
  bytes: TBytes;
  values, value: LPDWORD;
  i, numValues: Integer;  
begin
  // populate bytes as needed...
  values := LPDWORD(bytes);
  value := values;
  numValues := Length(bytes) div sizeof(DWORD);
  for I := 0 to numValues-1 do
  begin
    // use value^ as needed...
    Inc(value);
  end;
end;

或者,如果您使用的是Delphi 2009 +:

{$POINTERMATH ON}

var
  bytes: TBytes;
  values: LPDWORD;
  i, numValues: Integer;  
begin
  // populate bytes as needed...
  values := LPDWORD(bytes);
  numValues := Length(bytes) div sizeof(DWORD);
  for I := 0 to numValues-1 do
  begin
    // use values[i] as needed...
  end;
end;

答案 1 :(得分:0)

您可以定义其他类型:

TIEEE754Float = record
  case Boolean of   // Access to the same memory area
    True:
      (Byte1, Byte2, Byte3, Byte4: Byte);   // As 4 bytes
    False:
      (Float: Single);  // As 32-bit float
end;

我正在使用它进行MODBUS通讯

procedure TestTModbusRtu.TestWriteFrame;
const
  KS_45_ADDRESS = 2;
  DEVICE_ADDRESS = KS_45_ADDRESS;
  FUNCTION_CODE = TFunctionCode.fcWriteMultipleRegisters;
  MEMORY_ADDRESS = 16472;   // Set target temperature
  EXPECTED_VALUE = 45.5;
var
  frame: TFrame;
  value: TIEEE754Float;
begin
  frame.DeviceAddress := DEVICE_ADDRESS;
  frame.FunctionCode := FUNCTION_CODE;

  frame.DataArray[0] := MEMORY_ADDRESS div 256;   // Addresse (High Bit)
  frame.DataArray[1] := MEMORY_ADDRESS mod 256;   // Addresse (Low Bit)
  frame.DataArray[2] := 0;  // Anzahl des Wertes (High)
  frame.DataArray[3] := 2;  // Anzahl des Wertes (Low)
  frame.DataArray[4] := 4;  // Anzahl des Bytes geschickt

  value.Float := EXPECTED_VALUE;

  frame.DataArray[5] := value.Byte4;
  frame.DataArray[6] := value.Byte3;
  frame.DataArray[7] := value.Byte2;
  frame.DataArray[8] := value.Byte1;

  PrepareModbusRtuConnection(fModbusRtu);
  fModbusRtu.Connect;
  try
    fModbusRtu.WriteFrame(frame);

    ...

  finally
    fModbusRtu.Disconnect;
  end;
end;