Delphi编译器错误E2064:左侧不可被赋值

4
我继承了一个 Delphi 应用程序,但我对 Object Pascal 一无所知。
这是一个 BPL 文件,我需要将其编译到新版本的 C++ Builder XE 中。当我运行 make 命令时,会出现以下错误:
E2064 左侧不能被赋值。
我已经学习了足够的 Object Pascal 知识,以知道我有一个常量正在尝试被赋值。
但是,显然,您可以覆盖此行为;通过进入 Delphi 编译器下的“构建选项”,并打开“可分配类型常量”来将常量转换为变量。
我已经这样做了,但仍然遇到相同的错误。
我尝试使用 {$J+} 和 {$J-} 包围我的代码,但仍无法编译。
procedure TChunkIDAT.CopyInterlacedRGB8(const Pass: Byte;
  Src, Dest, Trans{$IFDEF Store16bits}, Extra{$ENDIF}: pChar );
var
  Col: Integer;
 begin
 {Get first column and enter in loop}
 Col := ColumnStart[Pass];
 Dest := pChar(Longint(Dest) + Col * 3);
 repeat
 {Copy this row}

  Byte(Dest^) := fOwner.GammaTable[pByte(Longint(Src) + 2)^]; inc(Dest);

在最后一行遇到了错误。如果我将const更改为var,那么我会得到一个错误,即声明与先前的声明不同,但我不知道先前的声明在哪里....


@jachguate 的目标是 XE,因此看起来这是一个 Unicode 问题。 - Jeroen Wiert Pluimers
我之前没有意识到我的速率只有38%。感谢您指出来,我会尝试修复一下。这是一个我没有编写的包(来自IOCOMP.com的第三方软件)。它是一组第三方VCL控件,用于在C++ Builder 6中进行编译,我正在尝试将其编译为CBuilder XE,因为他们还没有发布XE版本的工具。 - Eric
3个回答

9
你正在将一个两字节的东西(Char)强制转换为一个一字节的东西(Byte)。读取该值很容易定义,但使该值可写是棘手的,可能是因为形式和实际“var”参数的类型需要相同的原因。也许你想将其强制转换为两个字节的东西,例如Word。或者你想让GammaTable成为Char数组,这样你就不必进行任何类型转换了。或者,如果此代码最初是为2009年之前的Delphi版本编写的,则希望这些PChar声明为PAnsiChar - 字符类型已变得更宽。另一个选择是将Dest强制转换为PByte,然后解引用结果。不过,这可能是个坏主意,因为你只会覆盖缓冲区的每隔一个字节。
根据函数名称,似乎PChar从来不是正确的数据类型。该类型适用于字符数据,但我认为此代码正在处理字节。正确的做法可能是将PChar更改为PByte,然后您根本不需要对Dest进行类型转换。 $J指令与此无关;它控制编译器是否允许您向类型常量赋值。在此代码中您没有这些。

编译器仍应该容忍左侧转换,@Loren。有时这是有用的,例如当您想要分配接口变量的值而不触发引用计数时 - 只需将目标强制转换为“Pointer”。问题在于自Delphi 2009以来,大小不同。 - Rob Kennedy
我已经将所有的PChars替换成了PBytes,现在可以通过错误并使这个家伙编译和链接。然而,当我尝试安装生成的BPL时,我收到IOCOMP65包含单位Pnglang的消息,该单位也在vclimg150软件包中。通过调查上面的注释,我试图注释掉pngimage,但是我找不到它被包含在哪里。有什么提示吗? - Eric
打开 .DPK 包文件。项目管理器窗口应该显示项目中的文件列表,包括 Pnglang。在列表中选择该项并删除它。如果您收到有关 Pnglang 隐式添加到项目的警告,请不要忽略它。为了解决这个问题,将 vclimg150 添加到您的包的“requires”列表中。 - Rob Kennedy
所以我有一个BPK文件(不是DPK),其中有一个对vcljpg的引用,因此我将其删除,认为整个图像库(png,jpg)包含在vclimg150中?现在它可以编译但无法安装。抱怨jconsts单元,但在任何源文件中都找不到对jconsts的引用。请参见上面关于将pngimage重命名为pngimage2的注释。我想将其删除,但不确定如何操作。 - Eric
好的,这最终帮了我。非常感谢Rob! - Eric
显示剩余2条评论

2

原因是从Delphi 2009开始,Char、PChar和String都是Unicode格式,每个字符存储不止一个字节。
你不应该将这些指针强制转换为字节,并且如果你将赋值号左侧的内容强制转换为字节,则编译器会阻止你进行赋值操作。

以下代码可以通过编译:

procedure CopyInterlacedRGB8(const Pass: Byte; Dest: pAnsiChar); overload;
begin
  Byte(Dest^) := Pass;
end;

这不行:
procedure CopyInterlacedRGB8(const Pass: Byte; Dest: pChar); overload;
begin
  Byte(Dest^) := Pass;
end;

不要使用pChar,而应该使用pByte,这样代码会更简单:

procedure CopyInterlacedRGB8(const Pass: Byte; Dest: PByte); overload;
begin
  Dest^ := Pass;
end;

--jeroen


这看起来很有希望。我确实将许多pChar更改为pAnsiChar,但我没有更改函数参数。我将尝试并回报结果。 - Eric
那么在这个语句中的整数:Dest := pChar(Longint(Dest) + Col * 3); 有什么影响? - Linces Marques
1
@LincesMarques 这不会给你一个 Byte 值,而是一个指向 16 位 Char 的指针。重复循环仍然会失败,因为它会将指针增加 16 位,跳过 RGB 字节的一部分。 - Jeroen Wiert Pluimers

1

看起来你正在使用Gustavo Daud的TPngImage库。由于自D2009以来已经包含在RTL中,因此您不需要将该代码放在外部BPL中。从BPL中删除该单元,然后您就可以通过PngImage单元获取更新版本。


不确定-您可能是正确的。我们正在使用IOCOMP的VCL工具(http://www.iocomp.com/)。 - Eric
请你详细说明如何解决这个问题?我似乎找不到在任何hpp文件中包含pngimage的地方。 grep pngimage * iComponentEditorImageEditorPanel.hpp #include <pngimage.hpp> //Pascal单元 Iocomp65.tds:grep:输入行被截断-结果有问题 iVCLComponent.hpp #include <pngimage.hpp> //Pascal单元 pngimage.hpp //(请勿编辑:机器生成的标头)'pngimage.pas' rev: 22.00 PNGImage.pas 单位pngimage; pngzlib.pas {此单元将ZLIB链接到pngimage单元,以实现} - Eric
@Eric M:很抱歉,我不知道C++ Builder如何处理包和链接到.pas文件的问题。也许你可以提出一个新问题问一下? - Mason Wheeler
好的,自从我上次发布以来,我只是将所有的pngimage、pngzlib和pnglang副本重命名为pngimage2、pngzlib2和pnglang2。一切都还能正常编译,但当我安装时,会报告与JCONSTS的冲突,并且它在同一个vclimg150库中。我找不到源代码树中任何地方引用jconsts。 - Eric
@Eric M:很抱歉这里帮不上你太多。我只是碰巧认出了TChunkIDAT这个名称,因为在它被添加到RTL之前,我曾经经常使用PngImage。 - Mason Wheeler

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接