Old project cannot be compiled in Delphi 4 due to pointers issue

234 Views Asked by At

I'm not experienced in Delphi at all and I have a very old project that can be compiled in Delphi of 2nd,3rd versions but isn't working in Delphi 4. The problem is about pointers that are working differently in the newer version.

These pieces of code cause error "Variable required":

pEnabled := @pClrWire_s^.enabled;
pEnabled        := @Enabled;
pNEnabled    := @pName_s^.Enabled;

where pEnabled is:

const
pEnabled : ^boolean   = nil;

and pClrWire_s and pName_s are pointers as well:

pClrWire_s : TpImage;      {pointer to an image of colored wire}
pName_s    : TpNamed;      {pointer to the identifier}

Description of TpImage and TpNamed are found in other files of the project:

type
  TpImage   = ^TImage;
TpNamed = ^TNamed;
TNamed = class(TLabel)

Can this problem be solved without serious rewriting of the whole code? and what causes such problem with Delphi 4?

2

There are 2 best solutions below

5
On BEST ANSWER

Here is a complete solution tested with latest Delphi (D10.3 which really is Delphi version 26 if you compare with early Delphi version number, but that is an other story):

unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages,
  System.SysUtils, System.Variants, System.Classes,
  Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ExtCtrls;

type
  TpImage = ^TImage;

{$J+}   // enable writable constant
const
  pEnabled : ^boolean   = nil;

var
  pClrWire_s : TpImage;

type
  TForm1 = class(TForm)
  private

  public

  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

end.

As Dalija Prasnikar and Gerry Coll said in their respective comment, the key is to enable assignable typed constant. You can do it either using {$J+} in the source code or using the project options located at Project options / Building / Delphi compiler / Compiling / Syntax options / Asignable typed constant.

Let me know if it works for you.

0
On

The following minimal program works fine in Delphi4:

program ProjTestWriteableConstants; 
{$APPTYPE CONSOLE} 
{$J+} 
type 
  TMyPt = ^Boolean; 
const 
  pBool : TMyPt = nil; 
var 
  Enabled : Boolean; 
begin 
   pBool := @Enabled; 
end.

From Delphi 4 documentation:

Type       Switch

Syntax     {$J+} or {$J-}{$WRITEABLECONST ON} or {$WRITEABLECONST OFF}

Default    {$J+}{$WRITEABLECONST ON}

Scope      Local

The $J directive controls whether typed constants can be modified or not. In the {$J+} state, typed constants can be modified, and are in essence initialized variables. In the {$J-} state, typed constants are truly constant, and any attempt to modify a typed constant causes the compiler to report an error.

In previous versions of Delphi and Borland Pascal, typed constants were always writeable, corresponding to the {$J+} state. Old source code that uses writeable typed constants must be compiled in the {$J+} state, but for new applications it is recommended that you use initialized variables and compile your code in the {$J-} state.


Note:

  • The change from previous versions: In previous versions of Delphi and Borland Pascal, typed constants were always writeable, corresponding to the {$J+} state. Old source code that uses writeable typed constants must be compiled in the {$J+} state ...
  • The scope of the compiler directive {$J+} is local, which means that each unit that declares a writeable constant must include the {$J+} switch.

Conclusion: to make it work, you must put the compiler directive {$J+} in every unit where a writeable constant is declared.