【问题标题】:Delphi XE7 Android Record with String Element won't compile带有字符串元素的 Delphi XE7 Android Record 无法编译
【发布时间】:2015-07-11 04:38:50
【问题描述】:

在 Delphi FMX XE7、Win32 中,我有一个记录类型:

type TSettingsRec = record
  SessionTimeOut: Word;
  EventString: String[50];
end;

当我将 Target 更改为 Android 时,出现编译器错误:

[DCC 错误] MainForm.pas(45): E2029 ';'预期但找到“[”

我需要定义 EventString 元素的长度 [50],因为 TRecord 实际上是从数据库 (Firebird) 中读取的,该数据库是由 Delphi 7 程序使用 Bin2Hex 写入数据库的(原因只有该程序的作者):

var
  rec: TSettingsRec;
  settings: string;

SetLength(settings, SizeOf(rec)*2);
BinToHex(@rec, @settings[1]), SizeOf(rec));

我在使用 XE7 (win32) 时有效地解码:

var
  rec: TSettingsRec;
  settings: String;

SetLength(settings, SizeOf(rec) * 2);
System.Classes.HexToBin(Pchar(settings), @rec, SizeOf(rec));

但这不起作用,当我为 Android 编译时。那么如何在Android平台上指定EventString的长度[50]呢?

【问题讨论】:

  • EventString: array [0..49] of Char;?
  • @Abelisto 您错过了长度字节,并且还使用了错误的元素类型。它应该是 AnsiChar 或 Byte。
  • @DavidHeffernan 不。我只是相信平台依赖的编译器必须使用平台兼容的类型。如果不是 - 这是错误的编译器(换句话说就是汇编器)
  • @nolaspeaker 接受或拒绝答案,我们都在等待您的决定!
  • @abelisto 你不明白我说了什么,或者问题在问什么

标签: android delphi firemonkey delphi-xe7


【解决方案1】:

您不能在移动编译器上使用短字符串。您需要重新考虑代码。可能是这样的:

type
  TSettingsRec = record
  private
    FSessionTimeOut: Word;
    FEventStringLength: Byte;
    FEventString: array [0..49] of Byte; // ANSI encoded
    function GetEventString: string;
    procedure SetEventString(const Value: string);
  public
    property SessionTimeOut: Word read FSessionTimeOut write FSessionTimeOut;
    property EventString: string read GetEventString write SetEventString;
  end;

这复制了旧版短字符串的内存布局。这是一个包含字符串长度的单个字节,后跟一个长度为 50 的数组,包含有效负载的 ANSI 编码文本。该记录使用更自然的属性包装了遗留布局,这使得该类型更易于使用。

当然,我们仍然需要编写这些属性。像这样:

function TSettingsRec.GetEventString: string;
var
  Bytes: TBytes;
begin
  SetLength(Bytes, Min(FEventStringLength, Length(FEventString)));
  Move(FEventString, Pointer(Bytes)^, Length(Bytes));
  Result := TEncoding.ANSI.GetString(Bytes);
end;

procedure TSettingsRec.SetEventString(const Value: string);
var
  Bytes: TBytes;
begin
  Bytes := TEncoding.ANSI.GetBytes(Value);
  FEventStringLength := Min(Length(Bytes), Length(FEventString));
  Move(Pointer(Bytes)^, FEventString, FEventStringLength);
end;

这将适用于 Windows,但不适用于移动编译器,因为 TEncoding.ANSI 没有任何意义。因此,您需要使用所需的代码页创建编码。例如:

Encoding := TEncoding.Create(1252);

请注意,我什至没有编译此代码,所以它可能有一些皱纹。但我认为这里展示的概念是推动代码前进的最简洁的方式。我会让你为你的设置制定适当的细节。

【讨论】:

  • 我猜是因为你迟到了 6 分钟? +1
  • 我没有得到 dv。我想知道是否有明显的错误,以便我修复它。
  • 我也不懂DV。对我来说,这似乎是一个深思熟虑的答案。
  • 到目前为止这看起来不错,但设置字符串的解码对我来说仍然不清楚。假设我有 const 设置 = ''0C00F40158021E000E30313B30323B30333B30343B30350000000000000000000000000000000000000000000000000000000000000000000000000; System.Classes.HexToBin(Pchar(settings), @rec, SizeOf(rec)); 的替换代码在哪里
  • 澄清一下,我的意思是您用来生成十六进制的记录除了问题中显示的之外还有一些额外的成员。
【解决方案2】:

String[50] 在移动平台上不受支持。这是一种称为 ShortString 的旧数据类型,由 51 个字节的数据组成,其中第一个字节是字符串的长度,接下来的 50 个字节是定义字符串值的 8 位字符。

等效定义为array[0..50] of byte,其中第一个字节定义实际数据的长度。使用byte 是因为移动平台不支持AnsiChar(没有第三方补丁)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多