Attached is a sample application reproducing the problem. Compile the program with FPC 2.6.4 and everything works. Compile it with FPC 3.x and no interface reference is ever returned.

Sample output:


=======[ compiled with FPC 3.0.0, 3.0.2, 3.0.4 and 3.1.1]============
[tmp]$ ./project1
TClassA: ICmdLine interface is not supported!
TClassB: ICmdLine interface is not supported!
TClassC: ICmdLine interface is not supported!


=======[ compiled with FPC 2.6.4]============
[tmp]$ ./project1
TCmdLineImpl: ICmdLine.MyProc implementation
TCmdLineImpl: ICmdLine.MyProc implementation
TCmdLineImpl: ICmdLine.MyProc implementation



I did some further testing. In the attached project I have a dedicated class that implements the interface, then another class that implements the interface using interface delegation. If I change the sample code and NOT use interface delegation, but let TClassA directly implement the ICmdLine interface, then everything works.

But developers shouldn't need to be forced to do this. FPC support interface delegation and the real interface is a lot more complex to implement than the very simplified attached example. The nail in the coffin is that it used to work in FPC 2.6.4, but is now broken in FPC 3.x


Regards,
  Graeme

--
fpGUI Toolkit - a cross-platform GUI toolkit using Free Pascal
http://fpgui.sourceforge.net/

My public PGP key:  http://tinyurl.com/graeme-pgp
program project1;

{$mode objfpc}{$H+}
{$interfaces corba}

uses
  Classes, SysUtils;

type
   ICmdLine = interface
   ['{1D27F8F3-C0EE-11E7-87C3-C86000E37EB0}']
     procedure MyProc;
   end;

   // class implementing the interface
   TCmdLineImpl = class(TObject, ICmdLine)
      procedure MyProc;
   end;

   // class implementing the interface via interface delegation
   TClassA = class(TObject, ICmdLine)
   private
    FCmdLineParams: TCmdLineImpl;
    function    GetCmdLineParamsInterface: ICmdLine;
    property    CmdLineParams: ICmdLine read GetCmdLineParamsInterface implements ICmdLine;
   public
     destructor Destroy; override;
   end;

    TClassB = class(TClassA);

    TClassC = class(TClassB);



function TClassA.GetCmdLineParamsInterface: ICmdLine;
begin
  if not Assigned(FCmdLineParams) then
    FCmdLineParams := TCmdLineImpl.Create;
  Result := FCmdLineParams; // compiler does an implicit: FCmdLineParams as TCmdLineImpl
end;

destructor TClassA.Destroy;
begin
  FreeAndNil(FCmdLineParams);
  inherited Destroy;
end;

{ TCmdLineImpl }

procedure TCmdLineImpl.MyProc;
begin
  writeln(ClassName + ': ICmdLine.MyProc implementation');
end;

var
  c: ICmdLine;
  objA: TClassA;
  objB: TClassB;
  objC: TClassC;
begin
  objA := TClassA.Create;
  try
    if Supports(objA, ICmdLine, c) then
      c.MyProc
    else
      writeln('TClassA: ICmdLine interface is not supported!');
  finally
    FreeAndNil(objA);
  end;

  objB := TClassB.Create;
  try
    if Supports(objB, ICmdLine, c) then
      c.MyProc
    else
      writeln('TClassB: ICmdLine interface is not supported!');
  finally
    FreeAndNil(objB);
  end;

  objC := TClassC.Create;
  try
    if Supports(objC, ICmdLine, c) then
      c.MyProc
    else
      writeln('TClassC: ICmdLine interface is not supported!');
  finally
    FreeAndNil(objC);
  end;
end.

_______________________________________________
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal

Reply via email to