Delphi XE7 Android 带有字符串元素的记录无法编译
Delphi XE7 Android Record with String Element won't compile
在DelphiFMX XE7,Win32,我有一个记录类型:
type TSettingsRec = record
SessionTimeOut: Word;
EventString: String[50];
end;
当我将目标更改为 Android 时,出现编译器错误:
[DCC Error] MainForm.pas(45): E2029 ';' expected but '[' found
我需要定义 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]呢?
String[50]
在移动平台上不受支持。这是一种称为 ShortString
的遗留数据类型,由 51 个字节的数据组成,其中第一个字节是字符串的长度,接下来的 50 个字节是定义字符串值的 8 位字符。
等效定义为 array[0..50] of byte
,其中第一个字节定义实际数据的长度。使用 byte
是因为移动平台不支持 AnsiChar
(没有第 3 方补丁)。
您不能在移动编译器上使用短字符串。您需要重新考虑代码。大概是这样的:
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);
请注意,我什至没有编译这段代码,所以它可能有一些问题。但我认为这里展示的概念是推动代码向前发展的最简洁的方式。我会让你为你的设置制定适当的细节。
在DelphiFMX XE7,Win32,我有一个记录类型:
type TSettingsRec = record
SessionTimeOut: Word;
EventString: String[50];
end;
当我将目标更改为 Android 时,出现编译器错误:
[DCC Error] MainForm.pas(45): E2029 ';' expected but '[' found
我需要定义 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]呢?
String[50]
在移动平台上不受支持。这是一种称为 ShortString
的遗留数据类型,由 51 个字节的数据组成,其中第一个字节是字符串的长度,接下来的 50 个字节是定义字符串值的 8 位字符。
等效定义为 array[0..50] of byte
,其中第一个字节定义实际数据的长度。使用 byte
是因为移动平台不支持 AnsiChar
(没有第 3 方补丁)。
您不能在移动编译器上使用短字符串。您需要重新考虑代码。大概是这样的:
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);
请注意,我什至没有编译这段代码,所以它可能有一些问题。但我认为这里展示的概念是推动代码向前发展的最简洁的方式。我会让你为你的设置制定适当的细节。