View Issue Details

IDProjectCategoryView StatusLast Update
0023403FPCCompilerpublic2015-01-04 00:24
ReporterGraeme GeldenhuysAssigned To 
PrioritynormalSeverityminorReproducibilityalways
Status newResolutionopen 
Platformx86_64OSLinux OpenSUSEOS Version12.2
Product Version2.7.1Product Build 
Target VersionFixed in Version 
Summary0023403: Interface delegate class - incompatible with Delphi
DescriptionSee attached test project. Trying to compile this project as-is, will fail under FPC with the following "does not implement interface" error:

------------------------
Free Pascal Compiler version 2.7.1-rUnversioned directory [2012/11/15] for x86_64
Copyright (c) 1993-2012 by Florian Klaempfl and others
Target OS: Linux for x86-64
Compiling test.pas
test.pas(65,76) Error: Class "TMyIntfClass" does not implement interface "IMyIntf"
Fatal: Compilation aborted
An unhandled exception occurred at $0000000000564D25:
EAccessViolation: Access violation
  $0000000000564D25
------------------------

Yet, that same code compiles just fine under Delphi 7. In Delphi the delegate class is not required to mention the interfaces in the class definition.

Swapping lines 41 & 42 allows you to compile under FPC with CORBA interfaces. Thus you are forced under FPC to declare the interfaces in the class definition.

Using compiler mode 'objfpc' or 'delphi' doesn't make a difference here either.


Tagscorba, Delphi, interfaces
Fixed in Revision
FPCOldBugId
FPCTarget
Attached Files
  • test.pas (2,412 bytes)
    {
      A small test project to test the following:
       1) Interface delegation to another class
       2) Interface method resolution - overriding a interface implementation
     }
    program test;
    
    {$ifdef FPC}
      {$mode objfpc}{$H+}
      {$define UseCorba}   // Toggle if CORBA or COM interfaces should be used
    {$endif}
    
    {$ifdef MSWindows}
      {$APPTYPE CONSOLE}
    {$endif}
    
    {$ifdef UseCorba}
      {$interfaces corba}
    {$endif}
    
    uses
      Classes;
    
    //--------------  Interface  ------------------
    
    type
    
    {$ifdef UseCorba}
      IMyIntf = interface
    {$else}
      IMyIntf = interface(IInterface)
    {$endif}
      ['{ED858BD2-0E49-4B42-861D-6F415A7C0CF0}']
        procedure P1;
        procedure P2;
      end;
    
    
      { Delegation class }
    {$ifdef UseCorba}
    //  TMyIntfClass = class(TObject, IMyIntf)
      TMyIntfClass = class(TObject)
    {$else}
      {$ifdef FPC}
      TMyIntfClass = class(TInterfacedObject, IMyIntf)
      {$else}
      TMyIntfClass = class(TObject)     // NOTE: Delphi doesn't require you to mention interface here
      {$endif}
    {$endif}
      private
        { IMyIntf implementation }
        procedure P1;
        procedure P2;
      end;
    
    
    {$ifdef UseCorba}
      TMainForm = class(TObject, IMyIntf)
    {$else}
      TMainForm = class(TInterfacedObject, IMyIntf)
    {$endif}
      private
        FMyIntfClass: TMyIntfClass;
        { delegate IMyIntf implementation to another class }
        property MyIntfClass: TMyIntfClass read FMyIntfClass implements IMyIntf;
      public
        constructor Create; 
        destructor Destroy; override;
        procedure Run;
        { overrides the IMyIntf.P2 implementation using name resolution }
    //    procedure IMyIntf.P2 = MyP2;  
        procedure MyP2;
      end;
    
    
    
    //--------------  Implementation  ------------------
    
    
    procedure TMyIntfClass.P1;
    begin
      Writeln(Classname + '.P1');
    end;
    
    procedure TMyIntfClass.P2;
    begin
      Writeln(Classname + '.P2');
    end;
    
    
    
    constructor TMainForm.Create;
    begin
      FMyIntfClass := TMyIntfClass.Create;
    end;
    
    destructor TMainForm.Destroy;
    begin
      FMyIntfClass.Free;
      inherited Destroy;
    end;
    
    procedure TMainForm.Run;
    begin
      (self as IMyIntf).P1;
      (self as IMyIntf).P2;
    end;
    
    procedure TMainForm.MyP2;
    begin
      Writeln(Classname + '.MyP2');
    end;
    
    
    
    // ----- Application starting point  -----
    var
      frm: TMainForm;
    begin
      {$ifdef UseCorba}
      Writeln('CORBA interfaces are enabled');
      {$else}
      Writeln('COM interfaces are enabled');
      {$endif}
      frm := TMainForm.Create;
      try
        frm.Run;
      finally
        {$ifdef UseCorba}
        frm.Free;
        {$endif}
      end;
    end.
    
    test.pas (2,412 bytes)

Relationships

related to 0016531 new Partial interface delegation to class 

Activities

2012-11-28 18:17

 

test.pas (2,412 bytes)
{
  A small test project to test the following:
   1) Interface delegation to another class
   2) Interface method resolution - overriding a interface implementation
 }
program test;

{$ifdef FPC}
  {$mode objfpc}{$H+}
  {$define UseCorba}   // Toggle if CORBA or COM interfaces should be used
{$endif}

{$ifdef MSWindows}
  {$APPTYPE CONSOLE}
{$endif}

{$ifdef UseCorba}
  {$interfaces corba}
{$endif}

uses
  Classes;

//--------------  Interface  ------------------

type

{$ifdef UseCorba}
  IMyIntf = interface
{$else}
  IMyIntf = interface(IInterface)
{$endif}
  ['{ED858BD2-0E49-4B42-861D-6F415A7C0CF0}']
    procedure P1;
    procedure P2;
  end;


  { Delegation class }
{$ifdef UseCorba}
//  TMyIntfClass = class(TObject, IMyIntf)
  TMyIntfClass = class(TObject)
{$else}
  {$ifdef FPC}
  TMyIntfClass = class(TInterfacedObject, IMyIntf)
  {$else}
  TMyIntfClass = class(TObject)     // NOTE: Delphi doesn't require you to mention interface here
  {$endif}
{$endif}
  private
    { IMyIntf implementation }
    procedure P1;
    procedure P2;
  end;


{$ifdef UseCorba}
  TMainForm = class(TObject, IMyIntf)
{$else}
  TMainForm = class(TInterfacedObject, IMyIntf)
{$endif}
  private
    FMyIntfClass: TMyIntfClass;
    { delegate IMyIntf implementation to another class }
    property MyIntfClass: TMyIntfClass read FMyIntfClass implements IMyIntf;
  public
    constructor Create; 
    destructor Destroy; override;
    procedure Run;
    { overrides the IMyIntf.P2 implementation using name resolution }
//    procedure IMyIntf.P2 = MyP2;  
    procedure MyP2;
  end;



//--------------  Implementation  ------------------


procedure TMyIntfClass.P1;
begin
  Writeln(Classname + '.P1');
end;

procedure TMyIntfClass.P2;
begin
  Writeln(Classname + '.P2');
end;



constructor TMainForm.Create;
begin
  FMyIntfClass := TMyIntfClass.Create;
end;

destructor TMainForm.Destroy;
begin
  FMyIntfClass.Free;
  inherited Destroy;
end;

procedure TMainForm.Run;
begin
  (self as IMyIntf).P1;
  (self as IMyIntf).P2;
end;

procedure TMainForm.MyP2;
begin
  Writeln(Classname + '.MyP2');
end;



// ----- Application starting point  -----
var
  frm: TMainForm;
begin
  {$ifdef UseCorba}
  Writeln('CORBA interfaces are enabled');
  {$else}
  Writeln('COM interfaces are enabled');
  {$endif}
  frm := TMainForm.Create;
  try
    frm.Run;
  finally
    {$ifdef UseCorba}
    frm.Free;
    {$endif}
  end;
end.
test.pas (2,412 bytes)

Marco van de Voort

2015-01-04 00:24

manager   ~0080093

Still the case:

Free Pascal Compiler version 2.7.1 [2015/01/01] for i386
Copyright (c) 1993-2014 by Florian Klaempfl and others
Target OS: Win32 for i386
Compiling test.pas
test.pas(65,76) Error: Class "TMyIntfClass" does not implement interface "IMyInt
f"
Fatal: Compilation aborted
An unhandled exception occurred at $004EA5F8:
EAccessViolation: Access violation
  $004EA5F8 TVMTBUILDER__IS_NEW_VMT_ENTRY, line 2643 of nobj.pas
  $004EBF2E TVMTBUILDER__GENERATE_VMT, line 818 of nobj.pas
  $004E7A00 TYPE_DEC, line 876 of pdecl.pas
  $0053F8B5 PROC_PROGRAM, line 2128 of pmodules.pas
  $00433D59 COMPILE, line 376 of parser.pas
  $00414D90 COMPILE, line 269 of compiler.pas

Error: c:\pp32\bin\i386-win32\ppc386.exe returned an error exitcode

Issue History

Date Modified Username Field Change
2012-11-28 18:17 Graeme Geldenhuys New Issue
2012-11-28 18:17 Graeme Geldenhuys File Added: test.pas
2012-11-28 18:18 Graeme Geldenhuys Tag Attached: corba
2012-11-28 18:18 Graeme Geldenhuys Tag Attached: Delphi
2012-11-28 18:18 Graeme Geldenhuys Tag Attached: interfaces
2012-11-29 05:28 Sergei Gorelkin Relationship added related to 0016531
2015-01-04 00:24 Marco van de Voort Note Added: 0080093