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