为 Delphi 7 编译 HtmlViewer 组件时出错
Error compiling HtmlViewer component for Delphi 7
我正在尝试为 Delphi 7 (https://github.com/BerndGabriel/HtmlViewer) 编译 HtmlViewer 组件。打开 package subdir
下的项目 Frameviewer7.dpk
但是我收到以下编译错误:
HtmlBuffer.pas(1611):需要数组类型。
对应如下代码:
if FStart.BytePtr[0] = 0
FStart定义为FStart: TBuffPointer;
TBuffPointer = record
case Integer of
0: (BytePtr: PByte;);
1: (WordPtr: PWord;);
2: (AnsiChr: PAnsiChar;);
3: (WideChr: PWideChar;);
end;
不确定这里有什么问题。我的编译器是 Delphi7
FStart.BytePtr[0]
表示FStart.BytePtr
是一个数组,这个表达式的值是这个数组的第一个(第0)个元素。
然而,FStart.BytePtr
实际上是一个指针。但通常您可以使用数组和指针来完成相同的任务——您可以使用 TSomeType
的数组,或者使用指向 TSomeType
项的内存列表中第一个元素的指针。
我想这就是这里发生的事情。因此,您想要获取 byte
值列表的第一项,第一项出现在地址 FStart.BytePtr
。要在此位置获取 byte
,您可以使用 ^
取消引用指针:FStart.BytePtr^
.
您找到的代码尝试使用指针上的数组表示法访问数据。这种语法糖可能适用于某些更新版本或 Delphi,或使用某些编译器选项。 (我不记得了。)
此语法使用后来的 Delphi 编译器的一项功能,允许您使用索引引用来偏移类型化指针。在 Delphi 的某些版本中,这需要指定 POINTERMATH 编译器选项或指令。
不幸的是,Delphi 7.
不支持此功能
解决此问题的典型方法是使用数组类型并声明指向该数组类型的指针。数组类型的实际边界并不重要(从某种意义上说,您将使用指针类型,因此您不会创建实际的大型数组结构,仅将指针视为对此类结构的引用)。
唯一需要考虑的是,上限需要高于或等于您需要指定的最高索引,以使编译器满意您指定的任何文字索引可能有效。
即如果您指定了一个只有 100 个项目的数组,那么任何试图引用第 101 个项目的代码都将在编译时或运行时(如果启用运行时检查)无法进行边界检查。
因此,对于一个简单的示例,我们将使用一个包含 65535 个项目的数组:
const
MAX_BYTEARRAYDIM = 65535;
type
TByteArray = array[0..MAX_BYTEARRAYDIM] of Byte;
PByteArray = ^TByteArray;
procedure SomeExampleMethod;
var
pb: PByteArray;
begin
// ..
pb[12] := 25; // The array type is 0 based so this sets the value of byte offset 12 bytes from the address in pb
end;
这具有可移植到 Delphi.
的所有版本的优势(如果您的代码需要考虑这一点)
您的申请
在您的特定情况下,您可以通过这种方式重新定义 BytePtr 类型。不熟悉 HTMLViewer 代码我不能说这是否可行。
另一种方法是声明必要的数组和指针类型,并根据需要进行类型转换,例如:
if PByteArray(FStart.BytePtr)[0] = 0
当然,同样的技术可以根据需要应用于其他指针类型。
我正在尝试为 Delphi 7 (https://github.com/BerndGabriel/HtmlViewer) 编译 HtmlViewer 组件。打开 package subdir
下的项目 Frameviewer7.dpk但是我收到以下编译错误: HtmlBuffer.pas(1611):需要数组类型。
对应如下代码:
if FStart.BytePtr[0] = 0
FStart定义为FStart: TBuffPointer;
TBuffPointer = record
case Integer of
0: (BytePtr: PByte;);
1: (WordPtr: PWord;);
2: (AnsiChr: PAnsiChar;);
3: (WideChr: PWideChar;);
end;
不确定这里有什么问题。我的编译器是 Delphi7
FStart.BytePtr[0]
表示FStart.BytePtr
是一个数组,这个表达式的值是这个数组的第一个(第0)个元素。
然而,FStart.BytePtr
实际上是一个指针。但通常您可以使用数组和指针来完成相同的任务——您可以使用 TSomeType
的数组,或者使用指向 TSomeType
项的内存列表中第一个元素的指针。
我想这就是这里发生的事情。因此,您想要获取 byte
值列表的第一项,第一项出现在地址 FStart.BytePtr
。要在此位置获取 byte
,您可以使用 ^
取消引用指针:FStart.BytePtr^
.
您找到的代码尝试使用指针上的数组表示法访问数据。这种语法糖可能适用于某些更新版本或 Delphi,或使用某些编译器选项。 (我不记得了。)
此语法使用后来的 Delphi 编译器的一项功能,允许您使用索引引用来偏移类型化指针。在 Delphi 的某些版本中,这需要指定 POINTERMATH 编译器选项或指令。
不幸的是,Delphi 7.
不支持此功能解决此问题的典型方法是使用数组类型并声明指向该数组类型的指针。数组类型的实际边界并不重要(从某种意义上说,您将使用指针类型,因此您不会创建实际的大型数组结构,仅将指针视为对此类结构的引用)。
唯一需要考虑的是,上限需要高于或等于您需要指定的最高索引,以使编译器满意您指定的任何文字索引可能有效。
即如果您指定了一个只有 100 个项目的数组,那么任何试图引用第 101 个项目的代码都将在编译时或运行时(如果启用运行时检查)无法进行边界检查。
因此,对于一个简单的示例,我们将使用一个包含 65535 个项目的数组:
const
MAX_BYTEARRAYDIM = 65535;
type
TByteArray = array[0..MAX_BYTEARRAYDIM] of Byte;
PByteArray = ^TByteArray;
procedure SomeExampleMethod;
var
pb: PByteArray;
begin
// ..
pb[12] := 25; // The array type is 0 based so this sets the value of byte offset 12 bytes from the address in pb
end;
这具有可移植到 Delphi.
的所有版本的优势(如果您的代码需要考虑这一点)您的申请
在您的特定情况下,您可以通过这种方式重新定义 BytePtr 类型。不熟悉 HTMLViewer 代码我不能说这是否可行。
另一种方法是声明必要的数组和指针类型,并根据需要进行类型转换,例如:
if PByteArray(FStart.BytePtr)[0] = 0
当然,同样的技术可以根据需要应用于其他指针类型。