Question

I've got a lot of older code that uses the old-style pascal object type that I'm trying to get working in Delphi 2009. It compiles, but there seems to be several problems dealing with virtual methods. It appears that this problem has already been reports on Quality Central:

http://qc.embarcadero.com/wc/qcmain.aspx?d=71723

I was hoping anyone who still uses these (PatrickvL maybe?) could respond with more information. We've got A LOT of code that uses objects and if this isn't going to get fixed, we're stuck. Thanks in advance!

Was it helpful?

Solution 4

I sent an e-mail to our local representatives from Embarcadero in regards to this problem and referred them to the report on Quality Central. They basically told us to move all objects to classes, so I'm guessing they're not planning on fixing this...ever. I think we've pretty much accepted that this is the way we have to go if we want to move forward, so now we just have to schedule that work before we can proceed with our upgrade to Delphi 2009.

Just wanted to thank everyone who tried to help, but I believe at this point it's a lost cause :-(

OTHER TIPS

If you're using virtual methods, then you're clearly accessing the objects by reference, not by value. That's how classes always work in Delphi, so switching to classes shouldn't be too hard.

For any object types that don't have virtual methods, you should be able to turn them into records. Records are allowed to have methods now, as well as visibility specifiers. The don't support inheritance, though.

Old-style objects have been deprecated since February 14, 1994, the release date of the first version of Delphi. They've been deteriorating ever since. You should have moved away from them years ago.

I must admit I had a couple of beers looking at this, just for the challenge :) You need some magic bytes. According to legend Old style objects ONLY create a space for the pointers if you use ANY virtual methods. No Virtual methods NO VMT.

The VMT pointer is ALWAYS FIRST with new style objects because they all declare virtual methods. Seems Someone forgot that with old style objects the VMT can come later. so assuming its a just one pointer this makes it work on my D2009. I'm not into the guts of the compiler, a guy called Dave Jewell who used to write for PC pro could possibly confirm that this will be stable...

Type
  PObject1 = ^TObject1;
  TObject1 = Object
    Magic: Array[0..3] of Byte; //or integer or whatever I was playing with the size
    FCount     : Integer;
    Constructor Init;
    Procedure Add; virtual; 
    Procedure Deduct; virtual; 
    end;

Type
  PObject2   = ^TObject2;
  TObject2   = Object(TObject1)
    Constructor Init;
    end;

Then after construction these work:

.
.
.
Object2^.Add;
Object2^.Deduct;

and I get the appropriate console output

I added an additional proc just to make sure that it worked for 2 virtuals :)

Incidentally they work whether you put the ^ or not 2009 knows what you mean :(

Lacking a proper fix from embracodeland You still may still have to alter each BASE object definition. Hopefully you could do it with find and insert/replace or Grep... Good luck.

Ok - Done that - I cannot get it to fail.... Is your D2009 Fully Patched? Project/Compiler Options?

For absolute certainty and comparison here are my units:

---------------Project File

program testD2009;

{$APPTYPE CONSOLE}

uses
  SysUtils,
  Object1U in 'Object1U.pas',
  Object2U in 'Object2U.pas';


Var
  Object1 : PObject1;
  Object2 : PObject2;
begin
  try
    Object1 := New(PObject1,Init);
    Object1^.Add;
    Object1^.Deduct;

    Object2 := New(PObject2,Init);
    Object2^.Add;
    Object2^.Deduct;
    readln;
  except
    on E:Exception do
      Writeln(E.Classname, ': ', E.Message);
  end;
end.

--------------Object1 unit

unit Object1U;

interface

uses SysUtils;

Type
  PObject1 = ^TObject1;
  TObject1 = Object
    Magic: Array[0..3] of Byte;
    FCount     : Integer;
    Constructor Init;
    Procedure Add; virtual; { removing virtual allows the program to run }
    Procedure Deduct; virtual; { removing virtual allows the program to run }
    end;

implementation


Procedure TObject1.Add;
begin
  Writeln('Object1 Add');
end;

procedure TObject1.Deduct;
begin
  Writeln('Object1 Deduct');
end;

Constructor TObject1.Init;
begin
  inherited;
  FCount      := 0;
  Writeln('TObject1 Init');
end;

end.

----------------Object 2 unit

unit Object2U;

interface

uses Object1U;

Type
  PObject2   = ^TObject2;
  TObject2   = Object(TObject1)
    Constructor Init;
    Procedure Add; virtual; { removing virtual allows the program to run }
    Procedure Deduct; virtual; { removing virtual allows the program to run }
   end;

implementation

procedure TObject2.Add;
begin
  Writeln('Object2 Add');
  inherited;
end;

procedure TObject2.Deduct;
begin
  Writeln('Object2 Deduct');
  inherited;
end;

Constructor TObject2.Init;
begin
  Inherited Init;
  fCount := 1;
  Writeln('TObject2:Init');
end;

end.

----------------Program Output:

TObject1 Init
Object1 Add
Object1 Deduct
TObject1 Init
TObject2:Init
Object2 Add
Object1 Add
Object2 Deduct
Object1 Deduct

Puzzled I am :).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top