[fpc-pascal] inherited interfaces not seen by queryinterface / supports
David Emerson
dle3ab at angelbase.com
Thu Oct 27 03:13:42 CEST 2016
Hi all,
I am a bit perplexed / disappointed to see that the Supports /
QueryInterface functions for interfaces are not behaving the way I would
expect them to behave, when using an interface that inherits from
another interface.
note, _obj_type_ might be TObject, TInterfacedObject, or TComponent.
{$mode objfpc}
type
i_1 = interface
['{6C8CF001-733C-4A2D-B41F-3B3FF1D266B4}']
procedure do_one;
end;
i_2 = interface (i_1)
['{E0F0FA05-96C3-4979-A58C-5FB5F1E37214}']
procedure do_two;
end;
t_2 = class (_obj_type_, i_2)
// i_2 inherits from i_1, compiler requires i_1 implementation
procedure do_one;
procedure do_two;
end;
var
two : t_2;
It seems that Supports (two, i_1) returns false -- even though Supports
(two, i_2) returns true, and i_2 inherits from i_1. QueryInterface
similarly fails (for COM interfaces)
It appears to me that the only way to get a proper i_1 result from these
functions is to define
t_2 = class (_obj_type_, i_2, i_1)
This is redundant, and a burden when there is a hierarchy of inherited
interfaces defined in different places.
Is there some other way, some mode or switch or something, that would
make a class definition automatically include interface-supports for
inherited interfaces?
(Also, in the source below there are a couple Access Violation crashes
noted, any ideas why?)
Thanks!
~David.
Free Pascal Compiler version 3.0.0 [2015/12/05] for x86_64 (linux - debian)
Here's my full program:
program inherit_intf;
{$mode objfpc}{$H+}
{$macro on}
{$define corba}
//{$define tcomp}
//{$define tintobj}
{$ifdef corba}
{$interfaces corba}
{$define _intf_str_ := 'CORBA'}
{$else COM interface}
{$interfaces com}
{$define _intf_str_ := 'COM'}
{$ifndef tcomp}
{$define tintobj}
{$endif}
{$endif}
{$ifdef tcomp}
{$define _obj_type_ := TComponent}
{$define _obj_str_ := 'TComponent'}
{$define _create_param_ := nil}
{$else}
{$define _create_param_ := }
{$ifdef tintobj}
{$define _obj_type_ := TInterfacedObject}
{$define _obj_str_ := 'TInterfacedObject'}
{$else}
{$define _obj_type_ := TObject}
{$define _obj_str_ := 'TObject'}
{$endif not tintobj}
{$endif tcomp}
uses
classes,
sysutils;
type
i_1 = interface
['{6C8CF001-733C-4A2D-B41F-3B3FF1D266B4}']
procedure do_one;
end;
i_2 = interface (i_1)
['{E0F0FA05-96C3-4979-A58C-5FB5F1E37214}']
procedure do_two;
end;
t_2 = class (_obj_type_, i_2)
procedure do_one;
procedure do_two;
end;
t_3 = class (t_2, i_1)
end;
procedure t_2.do_one;
begin
writeln ('one');
end;
procedure t_2.do_two;
begin
writeln ('two');
end;
var
two : t_2;
three : t_3;
res : i_1;
begin
writeln (_intf_str_, ' / ', _obj_str_);
two := t_2.Create (_create_param_);
three := t_3.Create (_create_param_);
writeln ('t_2 supports i_1? ', supports (two, i_1, res)); //
unexpectedly FALSE
writeln ('t_3 supports i_1? ', supports (three, i_1, res)); // TRUE
{$ifndef corba}
writeln ('t_2 QueryIntf i_1? ', S_OK = two.QueryInterface (i_1,
res)); // unexpectedly FALSE
writeln ('t_3 QueryIntf i_1? ', S_OK = three.QueryInterface (i_1,
res)); // TRUE for TComponent. CRASH - SIGSEGV for COM + TInterfacedObject
{$endif}
two := three;
writeln ('t_3 (t_2 var) supports i_1? ', supports (two, i_1, res));
// TRUE for TComponent. CRASH - SIGSEGV with COM + TInterfacedObject
end.
More information about the fpc-pascal
mailing list