Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Delphi compiler error E2064 left side cannot be assigned to

I inherited a Delphi application and I know nothing about object pascal.

It's a BPL that I need to compile into the new version of C++ Builder XE.
When I run a make I get the error:

E2064 left side cannot be assigned to.

I've learned enough obj pascal to know I have a constant that is trying to be assigned a value.

But, apparently, you can over ride this behanvior; essentially turning constants into vars by going into Build options under the Delphi compiler and turning on "Assignable Typed constants".

I did that and I continue to get the same error.

I tried surrounding my code with {$J+} and {$J-} and still it will not compile.

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);

Get the error on last line. If I change the const to a var, I then get the error that the declaration differs from the previous declaration but I have no idea where the previous declaration is....

like image 377
Eric Avatar asked Dec 17 '22 20:12

Eric


2 Answers

You're type-casting a two-byte thing (Char) into a one-byte thing (Byte). Reading that value is easy to define, but making that value writable is tricky, probably for the same reason the types of formal and actual "var" parameters need to be identical.

Maybe you wanted to type-cast it to a two-byte thing, such as Word. Or maybe you want GammaTable to be an array of Char so you don't have to type-cast at all. Or maybe, if this code was originally written for a Delphi version earlier than 2009, you want those PChar declarations to be PAnsiChar — character types have gotten wider. Another option is to type-cast Dest to PByte, and then dereference the result. That's probably a bad idea, though, because you'll only be overwriting every other byte of the buffer.

Based on the name of the function, it sounds like PChar was never the right data type to use. That type is for character data, but I think this code is dealing with bytes. The correct thing to do is probably to change PChar to PByte, and then you don't need to type-cast Dest at all.

The $J directive is irrelevant; it controls whether the compiler will allow you to assign values to typed constants. You don't have any of those in this code.

like image 196
Rob Kennedy Avatar answered Dec 28 '22 07:12

Rob Kennedy


The reason is that as of Delphi 2009, Char, PChar, and String are Unicode, and store more than one byte per character.
You should not cast those pointers to bytes, and the compiler prevents you from assigning them if you cast the left side of an assignment to a byte.

This compiles:

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

This doesn't:

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

Instead of pChar, you should use pByte, which makes the code simpler:

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

--jeroen

like image 35
Jeroen Wiert Pluimers Avatar answered Dec 28 '22 08:12

Jeroen Wiert Pluimers