0

I'm trying to convert my aplliction from Delphi XE8 to 10.2 Tokyo. I'm getting strange runtime exeptions with casting objects provided by interfafce acrocss packages ( bpl's). when I try to cast objects with "as" keyword I'm getting this exception during runtime:

Project Project1.exe raised exception class EInvalidCast with message 'Invalid class typecast'

Here is the code :

Interface in a separte package Plugin_interface.bpl :

unit MainIntf;

interface
  Type IMainInft = interface
  ['{FE08C4A2-069C-4B8C-BB1B-445348CAB6A0}']
    function GetForm : TObject;
  end;

implementation

end.

Interface implamentation provided in Project1.exe :

unit MainImpl;

interface
uses MainIntf;

  Type TMain = class(TInterfacedObject,IInterface,IMainInft)
    function GetForm : TObject;
end;


implementation
uses unit1;

function TMain.GetForm: TObject ;
begin
  result:=Form1; // interafce is implemented on the main form so Form1 is rechable form here
end;


end.

And finally in another package "plugin.bpl" I'm trying to obtain object from interface :

unit Plugin_main;

interface
uses Mainintf, Vcl.Forms;

type TPlugin = class (Tobject)
  IIMyRefernceToMianIntf: IMainInft;
end;

function RegisterPlugin(AMainIntf: IMainInft): TForm ; export;
procedure UnRegisterPlugin; export;

exports
  RegisterPlugin,
  UnRegisterPlugin;

var
 Plugin_obj:  TPlugin;

implementation
uses vcl.Dialogs,System.Classes ;

function RegisterPlugin(AMainIntf: IMainInft): TForm ;
var
 MyForm : TForm ;
begin
  Plugin_obj:=TPlugin.Create;
  Plugin_obj.IIMyRefernceToMianIntf:=AMainIntf;

  if AMainIntf.GetForm is TForm then
    Showmessage ('Great it is a Tform') // will not happen
  else
    Showmessage ('Sorry  it is not Tform'); // will happen 
  if TComponent (AMainIntf.GetForm).Classname='TForm1' then
    Showmessage ('What ?? It is TForm1 decsendant from TForm  so is it TForm after all ?!');  // will happen 
// result:=  AMainIntf.GetForm as TForm  -- This will rise na exception
  result:= TForm( AMainIntf.GetForm)  ; // this will work

end;

procedure UnRegisterPlugin;
begin
  Plugin_obj.Free;
end;
end.

Why cant I use "as" and "is" keyword . Only hard catsing will do, but i hate to do it . on XE8 compiler everything worked as expected - problem exists on XE 10.2 tokyo compiler

Rudy Velthuis
  • 28,387
  • 5
  • 46
  • 94
jackDph
  • 11
  • 4
    Are your projects compiled with runtime packages enabled? This kind of error usually means a single instance of the RTL/VCL libraries is not being shared across the executables, causing RTTI to be different in each executable. – Remy Lebeau Jun 13 '17 at 07:07
  • 1
    Thanks Remy - that's it - this option has moved in XE10.2 and is now called "Link with runtime packages" on a separte option page called " Runtime Packages" – jackDph Jun 13 '17 at 08:22
  • 1
    @jackDph: there is no XE 10.2. It is Delphi or RAD Studio 10.2, no XE in sight. The XE line stopped at XE8. – Rudy Velthuis Jun 13 '17 at 09:49
  • @RemyLebeau, you should really make this into an answer, or -better- find the duplicate and close it. – Johan Jun 13 '17 at 10:00

1 Answers1

-1

The "is" keyword checks the actual objects to see it is of the type you are asking. So, checking for this:

if AMainIntf.GetForm is TForm then
Showmessage ('Great it is a Tform') // will not happen

does not happen because GetForm returns TObject and not TForm. Checking with "is" means, also, that you are checking for castability, i.e. the ability to use the "as" keyword. Since, the "is" check fails, that command fails as well:

result:=  AMainIntf.GetForm as TForm;

Your next option here is to hard-cast GetForm the way you do it:

TForm(AMainIntf.GetForm);

which works because this casting does not check whether GetForm is of TForm type. Since you return a form in TMain, this hard-casting is safe bet for you.

Having said that, however, why don't you return TForm directly rather than TObject? Do you use IMainInft in other classes that return other types than TForm?

John Kouraklis
  • 686
  • 4
  • 12
  • The `as` operator will work as long as the object on the left has `TForm` somewhere in it's class hierarchy. The problem here (as Remy states in their comment above) is that the BPL was not sharing the type data with the executable so had a different `TForm`. – Nat Jun 22 '21 at 03:06