1

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?

Sib
  • 404
  • 4
  • 16
  • 6
    Most likely issue is there because Delphi 4 (I am guessing) does not have writeable constants turned on by default. http://docwiki.embarcadero.com/RADStudio/Rio/en/Writeable_typed_constants_(Delphi) – Dalija Prasnikar Feb 04 '20 at 16:10
  • 4
    Why is this code trying to write to a `const`? And why is it using a pointer to a pointer? `TImage` is a class type, so any variables of `TImage` type are already pointers. – Remy Lebeau Feb 04 '20 at 18:41
  • 1
    @RemyLebeau Writeable consts are an old hack for backwards compatibility with turbo pascal which had no variable initialization, afaik. – J... Feb 04 '20 at 22:55
  • 1
    I cannot make any sense out of why this code was written this way. It's trying to do everything the hardest way possible. – Jerry Dodge Feb 05 '20 at 03:38
  • This will not solve your issue, but why porting that code to a such old Delphi version? I suggest to use the latest version. – fpiette Feb 05 '20 at 14:56
  • @fpiette I tried it with Delphi 7, it returned me same mistakes and even some additional ones. So I decided to try to gradually port it to a less older version first as it seems an easier task. – Sib Feb 05 '20 at 15:06
  • Try adding the `{$J+}` (writeable constants on) conditional define before the declarations. However, a full rewrite may be better...but not an option if your not familiar with Object Pascal (I suspect the original developer wasn't either) – Gerry Coll Feb 06 '20 at 04:16
  • @GerryColl I tried {$J+} and it didn't help too. Yes, probably, complete rewriting would be the only proper solution. Thanks for your input everyone. – Sib Feb 06 '20 at 13:11
  • Try this: `program ProjTestWritableConstants; {$APPTYPE CONSOLE} {$J+} type TMyPt = ^Boolean; const pBool : TMyPt = nil; var Enabled : Boolean; begin pBool := @Enabled; end.` If it works in Delphi4, the error is in the way you use the compiler directive. – LU RD Feb 06 '20 at 14:39
  • Porting to Delphi 4 and then Delphi 7 will be more work. If you want useful help here, provide a [mcve]. – David Heffernan Feb 06 '20 at 15:04
  • @LURD aforementioned directive doesn't help, it seems it's not the case. – Sib Feb 06 '20 at 15:19
  • @DavidHeffernan , the code is large and complicated and heavily depends on other files in the project, so I'm not sure it makes sense to extract any piece of it without breaking dependencies. I have the code working in D2, D3 versions, but it's too large to post. I was curious if it's a minor problem of changed language syntax or the core issue of program structure. Unfortunately, the second reason is getting more obvious. – Sib Feb 06 '20 at 15:24
  • If you want help we need to see a complete piece of code. If you can't provide that I suggest that you remove the post. – David Heffernan Feb 06 '20 at 16:47
  • @DavidHeffernan it takes some times, because the file itself contains over 5000 of strings of code, as well as related files in the project. – Sib Feb 09 '20 at 13:46

2 Answers2

1

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.

Community
  • 1
  • 1
LU RD
  • 34,438
  • 5
  • 88
  • 296
0

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.

fpiette
  • 11,983
  • 1
  • 24
  • 46
  • "Asignable typed constant" is enabled in options and addition of {$J+} doesn't change anything. I'm not using the latest version of Delphi, have just tried it with D7 again, it has another list of imported libraries, so I can't compile your code properly. Perhaps I didn't well elaborate the problem in the first message, because the source of mistake isn't odd constant. Variable requires caused by strings of code : "pEnabled := @pClrWire_s^.enabled;", "pEnabled := @Enabled;" and "pNEnabled := @pName_s^.Enabled;" – Sib Feb 06 '20 at 12:52
  • Sorry but I have not such old Delphi version anymore. I suggest two things: (1) Download latest Delphi community edition (free) and try with it (2) Write the smallest program like I have done, program which reproduce your problem and then publish it here (or make it available for download). You can write it with any Delphi. – fpiette Feb 06 '20 at 18:04
  • My code can't be compiled with Delphi 7 because it make use of name spaces. You can simply remove it for D7. That is remove any "vcl." or "system." or 'WinApi." prefixes from the unit list in the uses clause. – fpiette Feb 06 '20 at 18:07
  • Yes, I changed the names of imported libraries, your code is working in D7/D4. However I can't solve my issue, it seems even more complicated. Thanks for your help! – Sib Feb 09 '20 at 13:43
  • At least I solved what you asked. Please mark my answer as correct. – fpiette Feb 09 '20 at 17:46